# Git Worktree per sviluppare branch in parallelo: un workflow pulito e isolato

> Canonical: https://vxi.me/it/posts/git-worktree-parallel-development/
> Locale: it-it
> Published: 2026-03-25
> Updated: 2026-03-25
> Markdown: https://vxi.me/it/posts/git-worktree-parallel-development.md

Il problema tipico dello sviluppo parallelo non è creare un altro branch. Git rende quella parte banale. Il vero problema è assicurarsi che ciò che stai testando sia davvero il branch appena modificato, che il servizio stia partendo dalla directory corretta e che il commit finale non trascini dentro file non correlati.

Alla fine ho adottato un pattern molto più pulito: mantenere stabile la directory del repository principale e usare `git worktree` per assegnare a ogni feature branch una propria directory di lavoro isolata. Da quando lo faccio in modo coerente, portare avanti più feature in parallelo sulla stessa macchina è diventato molto meno soggetto a errori.

Se stai cercando sviluppo parallelo di branch Git, un workflow con Git worktree o un processo pratico standard per branch isolati, questo articolo tratta esattamente quel caso.

## Perché ho smesso di affidarmi al continuo cambio di branch

Il problema centrale non è la creazione dei branch. È la contaminazione.

In un'unica directory di repository, cicli ripetuti di `checkout` tendono a produrre sempre gli stessi problemi:

- pensi di stare testando una nuova feature, ma il servizio attivo proviene ancora da un'altra directory
- artefatti di build di una feature finiscono in un altro branch
- `git add .` raccoglie in silenzio file che non dovrebbero mai essere committati
- bugfix e feature iniziano a condividere lo stesso workspace disordinato

È esattamente il tipo di problema che Git worktree risolve bene. Non ti aiuta solo a creare un branch più velocemente: dà a ogni branch un posto fisicamente separato in cui vivere.

## Le regole sulle directory che tengo fisse

Per mantenere il workflow noioso nel senso buono, tratto alcune convenzioni come non negoziabili:

- repository principale: `/Users/kuangyongjie/charting_library`
- root dei worktree: `/Users/kuangyongjie/worktrees`
- formato branch: `codex/<feature-name>`
- branch principale: `master`

Il repository principale serve quindi per stabilità e merge, mentre il lavoro sulle feature avviene in percorsi come:

```text
/Users/kuangyongjie/worktrees/hotspot-ff
```

Sembra un dettaglio, ma cambia molto. Quando il percorso stesso ti dice dove sei, diventa molto più difficile confondere il repo principale con un workspace di feature.

## Il flusso standard è breve, ma ogni passaggio conta

Per prima cosa assicurati che esista la root dei worktree:

```bash
mkdir -p /Users/kuangyongjie/worktrees
```

Poi crea un nuovo worktree e un nuovo branch a partire dal repository principale:

```bash
REPO=/Users/kuangyongjie/charting_library
WT=/Users/kuangyongjie/worktrees/<feature-name>
BRANCH=codex/<feature-name>
BASE=master

# If the remote is available, update master first
# git -C "$REPO" pull --rebase central "$BASE"

git -C "$REPO" worktree add "$WT" -b "$BRANCH" "$BASE"
cd "$WT"
git branch --show-current
```

L'output atteso è:

```text
codex/<feature-name>
```

Questa conferma è importante. Da quel momento in poi sviluppo, build e verifica locale dovrebbero rimanere all'interno di `"$WT"`.

## Sviluppo e test solo nella directory del branch

Una volta creato il worktree, provo a essere rigoroso: build ed esecuzione soltanto dalla directory di quel branch.

Per esempio, se il frontend è in una cartella annidata:

```bash
cd "$WT/trendradar-service/trendradar-web"
npm run build
# production obfuscated build
# npm run build:multi-layer
```

Una delle false piste di debugging più comuni è: “ho cambiato il codice, ma la pagina sembra ancora vecchia”. Molto spesso il codice è corretto. È il processo che sta girando da un'altra directory.

Quando qualcosa sembra stale, controllo prima il `cwd` del processo:

```bash
lsof -nP -iTCP:<port> | sed -n '1,5p'
ps -p <pid> -o pid,ppid,command
lsof -p <pid> | rg "cwd"
```

Devi verificare che la directory di lavoro corrente punti davvero a:

```text
/Users/kuangyongjie/worktrees/<feature-name>/...
```

Se non lo fa, probabilmente stai testando il branch sbagliato indipendentemente da ciò che Git mostra.

## In questo workflow uso quasi mai `git add .`

Qui rimango volutamente conservativo.

Con worktree paralleli preferisco mettere in stage solo i file interessati invece di prendere tutta la directory. È troppo facile committare accidentalmente residui runtime, snapshot locali, cache o file generati.

I colpevoli tipici sono:

- `__pycache__`
- `*.db`
- `snapshot_*`
- `.DS_Store`

Il mio schema abituale assomiglia quindi a:

```bash
cd "$WT"
git add <file1> <file2> <file3>
git status --short
git commit -m "feat/fix: <summary>"
```

Quel controllo extra con `git status --short` è piccolo, ma elimina parecchio rumore.

## Fai merge solo dal repository principale

Quando la feature è pronta, non faccio merge dall'interno del worktree. Torno al repository principale e lo faccio lì:

```bash
cd /Users/kuangyongjie/charting_library
git branch --show-current   # must be master

# If the remote is available, update first
# git pull --rebase central master

git merge --no-ff codex/<feature-name>
```

La parte importante non è tanto `--no-ff`, quanto essere davvero sul branch principale e nella directory del repository principale prima del merge.

Se compare:

```text
MERGE_HEAD exists
```

di solito significa che il merge precedente non è terminato correttamente. In quel caso:

```bash
git merge --abort
```

e poi ripeti la sequenza pull/merge.

Se devi anche fare push:

```bash
cd /Users/kuangyongjie/charting_library
git push <remote> master
```

Un dettaglio pratico: su questa macchina il remote più comune si chiama spesso `central`, non `origin`. È una caratteristica dell'ambiente, non un problema di Git worktree.

## Quando uso fast-forward invece di lasciare un merge commit

A volte il requisito è leggermente diverso: testare in una directory branch isolata e poi riportare tutto su main senza creare un merge commit.

In quel caso ha senso un flusso fast-forward. Per esempio:

```bash
cd /Users/kuangyongjie/charting_library
git checkout master
git pull --rebase central master

git worktree add /Users/kuangyongjie/worktrees/hotspot-ff -b codex/hotspot-ff master
```

Poi esegui il servizio soltanto da quel worktree:

```bash
cd /Users/kuangyongjie/worktrees/hotspot-ff/trendradar-service
./venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 9544
```

E verifica il `cwd` da un altro terminale:

```bash
lsof -nP -iTCP:9544 -sTCP:LISTEN
ps -p <PID> -o pid,ppid,command
lsof -a -p <PID> -d cwd -Fn
```

Vale la pena ripeterlo: “il branch ha superato i test” significa poco se il processo non è mai partito dalla directory corretta.

## Le regole che considero ormai obbligatorie

Se pensi di usare i worktree nel lungo periodo, manterrei almeno queste regole rigide:

- una feature per directory worktree
- un task o una conversazione per worktree
- eseguire `git branch --show-current` prima di iniziare
- eseguire `git status --short` prima di committare
- fare merge soltanto dal repository principale `master`

Nessuna è complicata. Ed è proprio per questo che funzionano.

## Problemi comuni

### La pagina locale mostra ancora il risultato vecchio

Non dare subito per scontato che la modifica al codice sia fallita.

Controlla prima che il `cwd` del processo sia dentro il worktree target. Poi verifica di aver davvero ricostruito gli asset dalla directory di quel branch.

### `fatal: 'origin' does not appear to be a git repository`

Di solito il nome del remote è sbagliato. Esegui:

```bash
git remote -v
```

e fai push al remote effettivo. In questo ambiente spesso è `central`.

### `MERGE_HEAD exists`

In genere significa che l'ultimo merge è rimasto incompleto. Esegui:

```bash
git merge --abort
```

e ricomincia il flusso di merge.

### Ho modificato solo file frontend. Devo riavviare il backend?

Di solito no. Se gli asset statici sono stati ricostruiti e deployati correttamente, spesso basta un refresh della cache.
