Sei a metà di un feature branch, tre file modificati e niente ancora committato, quando un collega ti scrive per un crash da null pointer in produzione. La mossa classica è git stash, checkout di main, risolvi, pusha, poi git stash pop sperando che il lavoro a metà non dipendesse dai file da cui sei appena scappato. git worktree salta tutto questo. Fa il checkout del branch di hotfix in una seconda cartella, accanto al tuo feature branch, entrambe appoggiate sullo stesso repository.

Cosa fa davvero git worktree

Un checkout normale ti dà i file di un branch alla volta: cambiare branch riscrive quei file sul posto. git worktree ti dà più checkout dello stesso repository, ognuno nella sua cartella con il proprio branch, e puoi modificarli in modo indipendente.

Non sono clone separati. Esiste esattamente una cartella .git con il database degli oggetti, i ref e la config, e ogni worktree legge e scrive lì. In una worktree secondaria, .git non è nemmeno una cartella: è un file di una riga che punta a quella condivisa. Per questo creare una worktree è quasi istantaneo e non aggiunge storia su disco.

C’è una sola restrizione che conta. Due worktree non possono avere lo stesso branch in checkout contemporaneamente, perché un branch punta a un solo commit corrente e due checkout che committano su di esso litigherebbero per quel puntatore. Tutto il resto è per-worktree, dai file non tracciati e l’index fino al commit su cui si trova HEAD.

Come creare una worktree per un hotfix

Dal tuo checkout esistente di myapp, su feature/checkout-flow con modifiche non committate:

1
git worktree add ../myapp-hotfix -b hotfix/null-pointer main

Questo crea ../myapp-hotfix accanto alla tua cartella attuale, con un nuovo branch hotfix/null-pointer creato da main e già in checkout al suo interno. La cartella originale resta su feature/checkout-flow, sporca e intatta.

1
2
3
4
cd ../myapp-hotfix
# risolvi il bug, commit, push
git push -u origin hotfix/null-pointer
cd ../myapp

Tornato nella cartella originale, il tuo lavoro sulla feature è esattamente dove l’avevi lasciato. Nessun pop da fare, nessuno stash da ricordare.

Senza -b, git worktree add <path> usa l’ultimo pezzo del percorso come nome del branch. Se non esiste un branch con quel nome, Git lo crea da HEAD; se esiste e non è già in checkout in un’altra worktree, Git lo mette in checkout. Usa -d (--detach) quando vuoi solo un commit da esplorare, senza nessun branch.

Come elencare, rimuovere e pulire le worktree

1
git worktree list
1
2
/home/user/myapp          3a1f9c2 [feature/checkout-flow]
/home/user/myapp-hotfix   7e04d81 [hotfix/null-pointer]

Una volta che l’hotfix è stato mergiato, rimuovi la worktree passando da Git invece di cancellare la cartella a mano:

1
git worktree remove ../myapp-hotfix

remove si rifiuta se la worktree ha file tracciati modificati o file non tracciati. Passa -f per forzare. Se la cartella scompare in un altro modo (un rm -rf per sbaglio, un job CI che crasha), Git mantiene la sua voce amministrativa e git worktree list continua a mostrarla. Rimuovi la voce obsoleta con:

1
git worktree prune

Esegui prima con -n per vedere cosa rimuoverebbe senza farlo davvero.

Alcune worktree devono restare per settimane: un branch di release di lunga durata, o un checkout su una share di rete che non è sempre montata. Blocca quelle così prune lascia stare la loro voce e move e remove si rifiutano di toccarle:

1
2
git worktree lock --reason "release branch, do not prune" ../myapp-release
git worktree unlock ../myapp-release

Fai l’unlock prima se vuoi spostarne una con git worktree move <path> <new-path>. Spostare o rimuovere una worktree bloccata senza prima sbloccarla richiede --force due volte: una scelta pensata apposta come override deliberato.

Quando usare git worktree oltre agli hotfix

Ogni volta che ti servono due checkout vivi invece di uno:

  • Revisionare una PR senza perdere il tuo punto. git worktree add ../myapp-review origin/some-pr-branch ti dà una copia compilabile del branch di qualcun altro, mentre il tuo lavoro resta in checkout dove era.
  • Eseguire git bisect senza bloccare tutto il resto. Un bisect sposta HEAD a ogni passo, quindi il checkout in cui lo esegui diventa inutilizzabile per qualsiasi altra cosa finché non finisci o non fai reset. Eseguilo in una worktree dedicata (vedi Git Bisect: Trovare il Commit che ha Introdotto un Bug) e continua a lavorare in quella principale.
  • Eseguire due job sul repository in parallelo. Una test suite lunga su un branch mentre modifichi un altro, oppure due agenti AI su task separati: ognuno ha bisogno della propria cartella di lavoro. Una worktree te la fornisce senza un secondo git clone e una seconda cartella .git da più gigabyte.

Quando non usare git worktree

Ogni worktree duplica la working tree, non il database degli oggetti. Dieci worktree di un repository con un checkout da 50 MB costano circa 500 MB di file su disco, anche con un solo .git. Per un cambio di contesto di cinque minuti, git stash costa meno e non lascia niente da pulire dopo.

I submodule sono il punto dolente. git worktree move non sposta una worktree che contiene submodule, e una nuova worktree parte con le cartelle dei submodule vuote finché non esegui git submodule update --init al suo interno. La stessa documentazione di Git definisce incompleto il supporto ai submodule nei checkout multipli, quindi per un superprogetto con molti submodule un clone separato resta la scelta più sicura.

Anche certi strumenti assumono una sola cartella di lavoro per repository. Un IDE o un file-watcher che lega la sua cache al percorso assoluto del repository può confondersi davanti alla stessa storia in due posti. Apri ogni worktree come progetto a sé, non come sottocartella della prima: di solito risolve il problema.

Se devi solo accantonare o annullare qualcosa nel checkout che hai già, git stash oppure git reset, revert o restore è lo strumento più leggero. La prossima volta che un hotfix arriva a metà di una feature, prova git worktree add prima di git stash e guarda quale dei due preferisci pulire dopo.

Articoli correlati