Git 2.5 propone da luglio 2015 un sostituto di contrib/workdir/git-new-workdir
: git worktree
Vedi commit 68a2e6a di Junio C Hamano ( gitster
) .
La nota di rilascio menziona :
Un sostituto per contrib/workdir/git-new-workdir
questo non si basa su collegamenti simbolici e rende più sicura la condivisione di oggetti e riferimenti rendendo consapevoli tra loro il mutuatario e i mutuatari.
Vedi commit 799767cc9 (Git 2.5rc2)
Ciò significa che è ora possibile fare ungit worktree add <path> [<branch>]
Crea <path>
e fai il checkout <branch>
. La nuova directory di lavoro è collegata al repository corrente, condividendo tutto tranne i file specifici della directory di lavoro come HEAD, index, ecc. La git worktree
sezione aggiunge:
Un repository git può supportare più alberi di lavoro , consentendo di estrarre più di un ramo alla volta.
A git worktree add
, un nuovo albero di lavoro è associato al repository.
Questo nuovo albero di lavoro è chiamato "albero di lavoro collegato" in contrapposizione al "albero di lavoro principale" preparato da " git init
" o " git clone
" .
Un repository ha un albero di lavoro principale (se non è un repository nudo) e zero o più alberi di lavoro collegati.
dettagli:
Ogni albero di lavoro collegato ha una sottodirectory privata nella directory del repository
$GIT_DIR/worktrees
.
Il nome della sottodirectory privata è in genere il nome base del percorso dell'albero di lavoro collegato, eventualmente aggiunto con un numero per renderlo univoco.
Ad esempio, quando $GIT_DIR=/path/main/.git
il comando git worktree add /path/other/test-next next
crea:
- l'albero di lavoro collegato in
/path/other/test-next
e
- crea anche una
$GIT_DIR/worktrees/test-next
directory (o $GIT_DIR/worktrees/test-next1
se test-next
è già stata presa).
All'interno di un albero di lavoro collegato:
$GIT_DIR
è impostato per puntare a questa directory privata (ad /path/main/.git/worktrees/test-next
esempio nell'esempio) e
$GIT_COMMON_DIR
è impostato per puntare indietro all'albero di lavoro principale $GIT_DIR
(ad es /path/main/.git
.).
Queste impostazioni vengono effettuate in un .git
file situato nella directory superiore dell'albero di lavoro collegato.
Quando hai finito con un albero di lavoro collegato puoi semplicemente cancellarlo.
I file amministrativi dell'albero di lavoro nel repository verranno infine rimossi automaticamente (vedere gc.pruneworktreesexpire
in git config
), oppure è possibile eseguirli git worktree prune
nell'albero di lavoro principale o collegato per ripulire eventuali file amministrativi non aggiornati.
Attenzione: c'è ancora una sezione git worktree
"BUGS" da tenere presente.
Il supporto per i sottomoduli è incompleto .
NON è consigliabile effettuare più checkout di un superprogetto.
Nota: con git 2.7rc1 (novembre 2015) puoi elencare i tuoi esercizi.
Vedere commettere bb9c03b , commettere 92718b7 , commettere 5.193.490 , commettere 1ceb7f9 , commettere 1ceb7f9 , commettere 5.193.490 , commettere 1ceb7f9 , commettono 1ceb7f9 (8 ottobre 2015), commettere 92718b7 , commettere 5.193.490 , commettere 1ceb7f9 , commettono 1ceb7f9 (8 ottobre 2015), commettere 5.193.490 , commit 1ceb7f9 (08 ott 2015), commit 1ceb7f9 (08 ott 2015) e commit ac6c561(02 ott 2015) di Michael Rappazzo ( rappazzo
) .
(Unito da Junio C Hamano - gitster
- in commit a46dcfb , 26 ott 2015)
worktree
: aggiungi list
il comando ' '
' git worktree list
' scorre l'elenco dei worktree e restituisce i dettagli del worktree, incluso il percorso del worktree, la revisione e il ramo attualmente estratti e se l'albero di lavoro è nudo.
$ git worktree list
/path/to/bare-source (bare)
/path/to/linked-worktree abcd1234 [master]
/path/to/other-linked-worktree 1234abc (detached HEAD)
C'è anche l'opzione di formato porcellana disponibile.
Il formato porcellana ha una riga per attributo.
- Gli attributi sono elencati con un'etichetta e un valore separati da un singolo spazio.
- Gli attributi booleani (come "nudo" e "distaccato") sono elencati solo come etichetta e sono presenti solo se e solo se il valore è vero.
- Una riga vuota indica la fine di un albero di lavoro
Per esempio:
$ git worktree list --porcelain
worktree /path/to/bare-source
bare
worktree /path/to/linked-worktree
HEAD abcd1234abcd1234abcd1234abcd1234abcd1234
branch refs/heads/master
worktree /path/to/other-linked-worktree
HEAD 1234abc1234abc1234abc1234abc1234abc1234a
detached
Nota: se SPOSTA una cartella worktree, devi aggiornare manualmente il gitdir
file.
Vedi commit 618244e (22 gennaio 2016) e commit d4cddd6 (18 gennaio 2016) di Nguyễn Thái Ngọc Duy ( pclouds
) .
Aiutato da: Eric Sunshine ( sunshineco
) .
(Unita da Junio C Hamano - gitster
- in commit d0a1cbc , 10 feb 2016)
Il nuovo documento in git 2.8 (marzo 2016) includerà:
Se si sposta un albero di lavoro collegato, è necessario aggiornare il gitdir
file " " nella directory della voce.
Ad esempio, se un albero di lavoro collegato viene spostato /newpath/test-next
e il suo .git
file punta a /path/main/.git/worktrees/test-next
, quindi aggiornare
/path/main/.git/worktrees/test-next/gitdir
al riferimento /newpath/test-next
.
Fai attenzione quando elimini un ramo: prima di git 2.9 (giugno 2016), potresti eliminarne uno in uso in un altro albero di lavoro.
Quando " git worktree
" è in uso la funzione, " git branch -d
" ha permesso la cancellazione di un ramo che è stato estratto in un altro worktree.
Vedi commit f292244 (29 mar 2016) di Kazuki Yamaguchi ( rhenium
) .
Aiutato da: Eric Sunshine ( sunshineco
) .
(Unita da Junio C Hamano - gitster
- in commit 4fca4e3 , 13 apr 2016)
branch -d
: rifiuta l'eliminazione di una filiale attualmente estratta
Quando un ramo viene estratto dall'albero di lavoro corrente, è vietato eliminare il ramo.
Tuttavia, quando il ramo viene estratto solo da altri alberi di lavoro, l'eliminazione ha esito negativo.
Utilizzare find_shared_symref()
per verificare se il ramo è in uso, non solo confrontandolo con HEAD dell'albero di lavoro corrente.
Allo stesso modo, prima di git 2.9 (giugno 2016), la ridenominazione di un ramo verificato in un altro gruppo di lavoro non modificava la TESTA simbolica in detto altro gruppo di lavoro.
Vedi commit 18eb3a9 (08 apr 2016) e commit 70999e9 , commit 2233066 (27 marzo 2016) di Kazuki Yamaguchi ( rhenium
) .
(Unito da Junio C Hamano - gitster
- in commit 741a694 , 18 apr 2016)
branch -m
: aggiorna tutti i HEAD per ogni worktree
Quando si rinomina un ramo, attualmente viene aggiornato solo HEAD dell'albero di lavoro corrente, ma è necessario aggiornare HEAD di tutti gli alberi di lavoro che puntano al vecchio ramo.
Questo è il comportamento corrente, / path / to / wt's HEAD non è aggiornato:
% git worktree list
/path/to 2c3c5f2 [master]
/path/to/wt 2c3c5f2 [oldname]
% git branch -m master master2
% git worktree list
/path/to 2c3c5f2 [master2]
/path/to/wt 2c3c5f2 [oldname]
% git branch -m oldname newname
% git worktree list
/path/to 2c3c5f2 [master2]
/path/to/wt 0000000 [oldname]
Questa patch risolve questo problema aggiornando tutte le HEAD dei worktree rilevanti durante la ridenominazione di un ramo.
Il meccanismo di blocco è ufficialmente supportato con git 2.10 (3 ° trimestre 2016)
Vedi commit 080739b , commit 6d30862 , commit 58142c0 , commit 346ef53 , commit 346ef53 , commit 58142c0 , commit 346ef53 , commit 346ef53 (13 giu 2016) e commit 984ad9e , commit 6835314 (03 giu 2016) di Nguyễn Thái Ngọc Duy ( pclouds
) .
Suggerito da: Eric Sunshine ( sunshineco
) .
(Unita da Junio C Hamano - gitster
- in commit 2c608e0 , 28 lug 2016)
git worktree lock [--reason <string>] <worktree>
git worktree unlock <worktree>
Se un albero di lavoro collegato è archiviato su un dispositivo portatile o su una condivisione di rete che non è sempre montato, è possibile impedire che i suoi file amministrativi vengano eliminati emettendo il git worktree lock
comando, specificando facoltativamente --reason
di spiegare perché l'albero di lavoro è bloccato.
<worktree>
: Se gli ultimi componenti del percorso nel percorso dell'albero di lavoro sono univoci tra gli alberi di lavoro, possono essere utilizzati per identificare i campi di lavoro.
Ad esempio, se devi solo lavorare alberi su " /abc/def/ghi
" e " /abc/def/ggg
", allora " ghi
" o " def/ghi
" sono sufficienti per puntare al precedente albero di lavoro.
Git 2.13 (2 ° trimestre 2017) aggiunge lock
un'opzione in commit 507e6e9 (12 aprile 2017) di Nguyễn Thái Ngọc Duy ( pclouds
) .
Suggerito da: David Taylor ( dt
) .
Aiutato da: Jeff King ( peff
) .
(Unita da Junio C Hamano - gitster
- in commit e311597 , 26 apr 2017)
Consentire di bloccare un worktree immediatamente dopo la sua creazione.
Questo aiuta a prevenire una corsa tra " git worktree add; git worktree lock
" e " git worktree prune
".
Quindi git worktree add' --lock
è l'equivalente di git worktree lock
after git worktree add
, ma senza condizioni di gara.
Git 2.17+ (Q2 2018) aggiunge git worktree move
/ git worktree remove
: vedi questa risposta .
Git 2.19 (Q3 2018) aggiunge --quiet
un'opzione " " per rendere " git worktree add
" meno prolisso.
Vedi commit 371979c (15 agosto 2018) di Elia Pinto ( devzero2000
) .
Aiutato da: Martin Ågren, Duy Nguyen ( pclouds
) e Eric Sunshine ( sunshineco
) .
(Unita da Junio C Hamano - gitster
- in commit a988ce9 , 27 ago 2018)
worktree
: aggiungi --quiet
opzione
Aggiungi l' --quiet
opzione ' ' a git worktree
, come per gli altri git
comandi.
' add
' è l'unico comando interessato da esso poiché tutti gli altri comandi, tranne ' list
', sono attualmente silenziosi per impostazione predefinita.
Nota che " git worktree add
" era solito fare un "trova un nome disponibile con stat e poi mkdir
", che è soggetto a razza.
Questo problema è stato risolto con Git 2.22 (Q2 2019) usando mkdir
e reagendo EEXIST
in un ciclo.
Vedi commit 7af01f2 (20 febbraio 2019) di Michal Suchanek ( hramrach
) .
(Unita da Junio C Hamano - gitster
- in commit 20fe798 , 09 apr 2019)
worktree
: correzione worktree add
gara
Git esegue un ciclo stat per trovare un nome di worktree disponibile e quindi lo fa mkdir
sul nome trovato.
Trasformalo in mkdir
loop per evitare un'altra invocazione di worktree aggiungi la ricerca dello stesso nome gratuito e la creazione della directory prima.
Git 2.22 (Q2 2019) corregge la logica per dire se un repository Git ha un albero di lavoro protegge " git branch -D
" dalla rimozione del ramo che è attualmente estratto per errore.
L'implementazione di questa logica è stata interrotta per i repository con un nome insolito, che purtroppo è la norma per i sottomoduli in questi giorni.
Vedi commit f3534c9 (19 apr 2019) di Jonathan Tan ( jhowtan
) .
(Unito da Junio C Hamano - gitster
- in commit ec2642a , 08 maggio 2019)
Codice Pull richiede 178 Approfondimenti
worktree
: aggiornamento is_bare
euristico
Quando " git branch -D <name>
" viene eseguito, Git di solito controlla prima se quel ramo è attualmente estratto.
Ma questo controllo non viene eseguito se la directory Git di quel repository non è su " <repo>/.git
", ad esempio se quel repository è un sottomodulo che ha la sua directory Git memorizzata come " super/.git/modules/<repo>
", ad esempio.
Ciò comporta l'eliminazione del ramo anche se è stato estratto.
Questo perché get_main_worktree()
negli worktree.c
insiemi is_bare
su un worktree usando solo l'euristica che un repository è nudo se il percorso del worktree non termina in " /.git
", e non nuda altrimenti.
Questo is_bare
codice è stato introdotto nel 92718b7 (" worktree
: aggiungi dettagli alla struttura del worktree", 2015-10-08, Git v2.7.0-rc0), seguendo un pre-core.bare
euristico.
Questa patch fa 2 cose:
- Insegna invece
get_main_worktree()
a utilizzare is_bare_repository()
, introdotto in 7d1864c ("Introduci is_bare_repository () e variabile di configurazione core.bare", 2007-01-07, Git v1.5.0-rc1) e aggiornato in e90fdc3 ("Pulizia della gestione dell'albero di lavoro", 2007 -08-01, Git v1.5.3-rc4).
Questo risolve il " git branch -D <name>
" problema descritto sopra.
Tuttavia ... Se un repository ha core.bare=1
ma il git
comando " " viene eseguito da uno dei suoi worktrees secondari, is_bare_repository()
restituisce false (il che va bene, poiché è disponibile un worktree).
E, trattare il gruppo di lavoro principale come non nudo quando è nudo causa problemi:
Ad esempio, la mancata eliminazione di un ramo da un albero di lavoro secondario a cui fa riferimento HEAD di un albero di lavoro principale, anche se tale albero di lavoro principale è nudo.
Per evitare ciò, controllare anche core.bare
durante l'impostazione is_bare
.
Se core.bare=1
, fidati, e altrimenti, usa is_bare_repository()
.
git-new-workdir
sarà sostituito dagit checkout --to=<path>
in Git 2.5. Vedi la mia risposta di seguito