Guida

git worktree: come lavorare su più branch contemporaneamente

Aggiornato: · Skillaria.Top

git worktree permette di collegare a un unico repository più cartelle di lavoro, ciascuna con il proprio branch aperto. Il comando git worktree add ../hotfix main crea accanto al progetto una cartella con il branch main; storia e oggetti sono condivisi e non serve clonare di nuovo nulla.

Cosa fa git worktree

git worktree collega a un unico repository più cartelle di lavoro. Nella cartella principale avete aperto il branch della feature, in quella accanto main per un hotfix urgente, ed entrambi esistono contemporaneamente. Oggetti, commit e branch sono condivisi: un commit fatto in una cartella è subito visibile nell'altra, senza push né fetch.

Senza worktree il cambio di contesto è così: git stash, git switch main, correzione, git switch di ritorno, git stash pop. Se il progetto ha una build lunga o un node_modules pesante, ogni cambio di branch invalida anche le cache. La seconda opzione è clonare di nuovo il repository, ma allora ottenete due copie indipendenti della storia, da sincronizzare tramite il server remoto.

Worktree offre il meglio dei due approcci: cartelle separate, ma un unico database .git. È possibile perché un branch in Git è solo un puntatore a un commit, non una copia dei file, e nulla impedisce a copie di lavoro diverse di guardare puntatori diversi.

Come creare una copia di lavoro aggiuntiva

La forma base del comando è git worktree add <percorso> [<branch>]. Vediamo le varianti principali.

Aprire un branch esistente

cd ~/projects/shop
git worktree add ../shop-main main
Preparing worktree (checking out 'main')
HEAD is now at 3f2c1ab Aggiorna il README

Accanto al progetto comparirà la cartella shop-main con il branch main. Entrateci con un normale cd e lavorate come in qualsiasi repository.

Creare un nuovo branch insieme alla copia di lavoro

git worktree add -b hotfix/payment-timeout ../shop-hotfix main

L'opzione -b crea il branch hotfix/payment-timeout da main e lo apre nella nuova cartella. L'opzione -B fa lo stesso, ma se il branch esiste già lo riporta al commit indicato: usatela con cautela.

Forma breve

git worktree add ../experiment

Se non indicate il branch, Git ne crea uno nuovo con il nome dell'ultimo componente del percorso (qui experiment) a partire dall'HEAD corrente. Se un branch con quel nome esiste già, verrà aperto quello.

Copia di lavoro senza branch

git worktree add --detach ../shop-v1.4 v1.4.0

La modalità detached HEAD è comoda per compilare o verificare una vecchia release a partire dal tag, senza creare branch superflui.

Un branch dal server remoto

git fetch origin
git worktree add ../review-auth feature/auth

Se il branch locale feature/auth non esiste ma ce n'è esattamente uno remoto, origin/feature/auth, Git crea un branch locale con il tracking, come con git switch feature/auth. Così è comodo fare la review della pull request di qualcun altro senza toccare il proprio lavoro.

Come vedere ed eliminare le copie di lavoro

git worktree list
/home/anna/projects/shop            a1b2c3d [feature/cart]
/home/anna/projects/shop-hotfix     7e8f9a0 [hotfix/payment-timeout]
/home/anna/projects/shop-v1.4       5d6e7f8 (detached HEAD)

La prima riga è la copia di lavoro principale (main worktree), le altre sono collegate (linked). Per gli script c'è l'output leggibile dalle macchine git worktree list --porcelain.

Quando l'hotfix è stato unito, eliminate la copia di lavoro:

git worktree remove ../shop-hotfix
git branch -d hotfix/payment-timeout

git worktree remove elimina la cartella e le voci di servizio. Se nella copia ci sono modifiche non committate o file non tracciati, il comando si rifiuterà di procedere; aggiungete --force solo se siete sicuri che non servano. Notate che il branch in sé non viene eliminato: va rimosso a parte.

Se la cartella è stata eliminata a mano

Eliminare la cartella dal file manager o con rm -rf lascia in .git/worktrees una voce «orfana», e il branch continua a risultare occupato. Ripulite queste voci:

git worktree prune --verbose

Git lo fa periodicamente anche da solo durante la garbage collection, ma non è necessario aspettare.

Come funziona internamente

In una copia di lavoro collegata, al posto della cartella .git c'è un file .git con una sola riga:

gitdir: /home/anna/projects/shop/.git/worktrees/shop-hotfix

In quella cartella di servizio sono conservati i dati specifici della copia di lavoro: il suo HEAD, il suo index (staging area), i suoi stati di merge e rebase. Tutto il resto è condiviso: oggetti, branch, tag, repository remoti, configurazione e hook.

Proprio di ogni copia di lavoroCondiviso da tutte
HEAD (branch o commit corrente)Oggetti e tutta la storia
Index (git add)Branch locali e remoti, tag
Merge, rebase, cherry-pick in corsoStash (refs/stash è condiviso)
File nella cartella di lavoro.git/config e hook

Dalla tabella emerge un dettaglio poco ovvio: git stash list in qualsiasi copia mostra le stesse voci. È persino comodo: potete mettere da parte le modifiche in una cartella e recuperarle in un'altra.

Il limite principale: un branch, una copia di lavoro

Non si può aprire lo stesso branch in due copie di lavoro. Se ci provate, Git risponde con un errore di questo tipo:

git worktree add ../shop-copy feature/cart
fatal: 'feature/cart' is already used by worktree at '/home/anna/projects/shop'

(nelle versioni più vecchie di Git il testo è «is already checked out at»). Il limite protegge dalla situazione in cui un commit in una cartella cambia silenziosamente il branch sotto i piedi dell'altra. Soluzioni: creare un nuovo branch dallo stesso commit (-b), aprire la copia in modalità --detach oppure, se proprio serve, usare --force conoscendone le conseguenze.

Per lo stesso motivo nella cartella principale non potrete eseguire git switch main finché main è aperto in una copia di lavoro vicina.

Scenari pratici

Hotfix urgente a metà di una feature

git worktree add -b hotfix/null-price ../shop-hotfix main
cd ../shop-hotfix
# correggiamo, testiamo
git commit -am "Correggi il crash con prezzo vuoto"
git push -u origin hotfix/null-price
cd ../shop
git worktree remove ../shop-hotfix

La vostra feature incompleta è rimasta com'era, non è stato necessario mettere nulla nello stash, e l'IDE con il progetto aperto non si è nemmeno accorto del cambio.

Review di una pull request con esecuzione del codice

Una copia separata per la review permette di compilare ed eseguire il branch di un collega, lanciare i test e intanto continuare il proprio lavoro nella finestra accanto dell'editor.

Confrontare il comportamento di due versioni

Due copie con tag diversi si possono avviare in parallelo su porte diverse e confrontare, ad esempio, la velocità di risposta dell'API prima e dopo un'ottimizzazione.

Test e build lunghi

Avviate l'esecuzione completa dei test in una copia e continuate a scrivere codice nell'altra: la build non si romperà perché state modificando dei file.

Più agenti AI in parallelo

Se sui compiti lavorano più agenti o processi, conviene dare a ciascuno la propria copia di lavoro sul proprio branch: non si intralciano a vicenda e i risultati finiscono subito nel repository comune.

Come organizzare le cartelle se usate worktree tutti i giorni

Se le copie di lavoro vi servono ogni giorno, stabilite una struttura, altrimenti le cartelle vicine diventeranno presto un caos. Uno schema diffuso: una cartella padre del progetto, che contiene un repository bare e una cartella per ogni branch:

git clone --bare git@example.com:team/shop.git ~/projects/shop/.bare
cd ~/projects/shop
echo "gitdir: ./.bare" > .git
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin

git worktree add main
git worktree add -b feature/cart feature-cart main

La riga con remote.origin.fetch serve perché un clone bare per impostazione predefinita non configura il tracking dei branch remoti. Il risultato: in ~/projects/shop ci sono le cartelle main e feature-cart, ciascuna con il proprio branch, e nessuna è «più principale» dell'altra.

Una seconda buona abitudine è chiamare la cartella come il branch (sostituendo la barra con un trattino). Così dall'output di git worktree list e dal percorso nel terminale è sempre chiaro dove vi trovate. Infine, eliminate la copia subito dopo il merge del branch: le copie di lavoro vecchie occupano spazio e tengono i branch «occupati».

Errori comuni e insidie

  • Dipendenze e build non sono condivise. Ogni copia è una cartella separata, quindi node_modules, l'ambiente virtuale Python, .env e gli artefatti di build vanno ricreati. I file non tracciati non vengono trasferiti nella nuova copia.
  • Copia di lavoro dentro la cartella principale. Il comando git worktree add ./hotfix crea una cartella dentro il progetto, e la copia principale la vedrà come file non tracciati. Tenete le copie accanto (../) o in una cartella separata, oppure aggiungete il percorso a .gitignore.
  • Cartella spostata a mano. Il collegamento si rompe. Spostate con git worktree move ../old ../new, e se l'avete già spostata, eseguite git worktree repair nella nuova cartella.
  • La copia su un disco rimovibile sparisce. Perché prune non elimini la voce della copia su un disco scollegato, bloccatela: git worktree lock --reason "disco esterno" ../shop-usb.
  • Sottomoduli. Il supporto dei submodule nelle copie di lavoro è limitato; dopo aver creato la copia eseguite git submodule update --init e controllate il risultato.

Promemoria di git worktree

CompitoComando
Aprire un branch esistente in una nuova cartellagit worktree add ../dir branch
Creare branch e copiagit worktree add -b new-branch ../dir main
Copia senza branch (tag, commit)git worktree add --detach ../dir v1.0
Elenco delle copiegit worktree list
Eliminare una copiagit worktree remove ../dir
Togliere le voci delle cartelle eliminategit worktree prune
Spostare una copiagit worktree move ../dir ../new-dir
Riparare i collegamenti dopo uno spostamentogit worktree repair
Proteggere da prunegit worktree lock ../dir

git worktree, stash o un secondo clone

Criteriostashworktreesecondo clone
Velocità del cambioRapido, ma con cambio di branchIstantaneo: è solo un'altra cartellaIstantaneo
Spazio su discoMinimoSolo i file di lavoroCopia completa della storia
SincronizzazioneNon serveNon serve, la storia è condivisaTramite push/fetch
Lavoro simultaneoNoSìSì

Lo stash resta la scelta migliore per brevi distrazioni di un paio di minuti. Per tutto ciò che dura di più, o quando servono due versioni aperte insieme, è più comodo worktree.

In sintesi

git worktree è un modo semplice per lavorare su più branch contemporaneamente: add crea una cartella, list le mostra, remove e prune le eliminano. La storia è condivisa, mentre HEAD, index e file sono propri di ogni copia; lo stesso branch non può essere aperto in due copie. Come sono fatti i branch e perché passare dall'uno all'altro è così leggero lo vediamo in dettaglio, nella pratica, nel corso su Git.

Domande frequenti

Da quale versione di Git esiste git worktree?

Il comando è comparso in Git 2.5 e da allora è stato molto migliorato, ad esempio remove e move sono stati aggiunti in seguito. In qualsiasi versione moderna di Git tutti i comandi descritti sono disponibili.

Si può fare un commit in una copia di lavoro e vederlo in un'altra?

Sì, la storia è condivisa. Il commit è subito visibile con git log in qualsiasi copia, e si può unire con git merge senza push né fetch.

L'IDE vede più copie di lavoro?

Per l'IDE ogni copia è una normale cartella di progetto, da aprire in una finestra separata. Molti editor mostrano anche l'elenco delle copie di lavoro nell'interfaccia Git integrata.

git worktree remove elimina il branch?

No, vengono eliminate solo la cartella e la voce di servizio. Il branch va eliminato a parte con git branch -d.

git worktree funziona con un repository bare?

Sì, uno schema diffuso è tenere un clone bare e creare da esso una copia di lavoro per ogni branch: in questo caso una cartella «principale» con i file non esiste affatto.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Git da zero a sviluppatore sicuro».

Vai al corso