Qual è la differenza tra HEAD, albero di lavoro e indice, in Git?


488

Qualcuno può dirmi la differenza tra HEAD, albero di lavoro e indice, in Git?

Da quello che ho capito, sono tutti nomi per diversi rami. La mia ipotesi è corretta?


modificare

ho trovato questo

Un singolo repository git può tracciare un numero arbitrario di rami, ma il tuo albero di lavoro è associato ad uno solo di essi (il ramo "corrente" o "estratto") e HEAD punta a quel ramo.

Questo significa che HEAD e l'albero di lavoro sono sempre gli stessi?


26
Rispetto alla tua modifica: assolutamente no. HEADè il commit sulla punta del ramo corrente. Se hai appena estratto il ramo, ovvero non hai file modificati, il suo contenuto corrisponde all'albero di lavoro. Non appena si modifica qualcosa, non corrisponde più.
Cascabel,

6
Penso che devi leggere questo: think-like-a-git.net
Andrzej Duś,

5
Vorrei anche aggiungere un Staging Areaa quell'elenco. Ciò che è HEAD, Working Tree, IndexeStaging Area
verde

2
L'ultima frase di @ Jefromi sarebbe più chiara in quanto:> Non appena modifichi qualcosa, l'albero di lavoro non corrisponde più al commit HEAD
starscream_disco_party

3
Per ogni lettura di questo in futuro, il modo migliore per comprendere veramente alcune di queste risposte è vedere, sentire e concettualizzare visivamente ciò che sta succedendo: questo è lo strumento migliore per l'apprendimento di git di sempre: onlywei.github.io/explain-git-with -d3 / # fetchrebase
BKSpurgeon

Risposte:


579

Alcuni altri buoni riferimenti su questi argomenti:

testo alternativo

Uso l'indice come checkpoint .

Quando sto per fare un cambiamento che potrebbe andare storto - quando voglio esplorare una direzione che non sono sicuro di poter seguire o anche se è una buona idea, come un refactoring concettualmente impegnativo o cambiare un tipo di rappresentazione: controllo il mio lavoro nell'indice. Se questa è la prima modifica che ho apportato dal mio ultimo commit, allora posso usare il repository locale come checkpoint, ma spesso ho una modifica concettuale che sto implementando come una serie di piccoli passi. Voglio fare il checkpoint dopo ogni passaggio, ma salvare il commit fino a quando non sono tornato al codice funzionante e testato.

Appunti:

  1. l'area di lavoro è la struttura di directory dei file (di origine) visualizzati e modificati.

  2. L' indice è un singolo file binario di grandi dimensioni <baseOfRepo>/.git/index, che elenca tutti i file nel ramo corrente, i loro checksum sha1 , i timestamp e il nome del file - non è un'altra directory con una copia dei file al suo interno.

  3. Il repository locale è una directory nascosta ( .git) che include una objectsdirectory contenente tutte le versioni di ogni file nel repository (rami locali e copie di rami remoti) come file compresso "BLOB".

Non pensare ai quattro "dischi" rappresentati nell'immagine sopra come copie separate dei file repo.

testo alternativo

Praticamente sono nominati riferimenti per i commit di Git. Esistono due tipi principali di ref: tag e head.

  • I tag sono riferimenti fissi che contrassegnano un punto specifico nella storia, ad esempio v2.6.29.
  • Al contrario, i capi vengono sempre spostati per riflettere la posizione attuale dello sviluppo del progetto.

testo alternativo

(nota: come commentato da Timo Huovinen , quelle frecce non sono ciò a cui puntano le commit, è l' ordine del flusso di lavoro , che mostra sostanzialmente le frecce come 1 -> 2 -> 3 -> 4dove 1è il primo commit ed 4è l'ultimo)

Ora sappiamo cosa sta succedendo nel progetto.
Ma per sapere cosa sta succedendo proprio qui, proprio ora c'è un riferimento speciale chiamato HEAD. Serve due scopi principali:

  • indica a Git quale commit prende i file da quando effettui il checkout e
  • indica a Git dove inserire nuovi commit quando si commette.

Quando lo esegui git checkout ref, punta HEADal riferimento che hai designato ed estrae i file da esso. Quando lo esegui git commit, crea un nuovo oggetto commit, che diventa un figlio di corrente HEAD. Normalmente HEADindica una delle teste, quindi tutto funziona bene.

testo alternativo


20
Dopo aver letto molte volte su git, non l'ho mai capito completamente, mi sono davvero frustrato n voglio usare la parola f; Ma sono in comunità! Hai menzionato le teste ma nelle immagini sopra c'è sempre una singola TESTA dove sono le rimanenti teste? "Normalmente HEAD indica una delle teste, quindi tutto funziona bene." Ti prego di spiegarlo, dichiarazione Ur.
Necktwi,

12
@neckTwi HEAD è il commit corrente con cui stai lavorando ( stackoverflow.com/a/964927/6309 ). Di solito è una delle "teste di ramo" (una delle commit a cui fanno riferimento i rami, che rappresenta la punta di detti rami). Ma puoi effettuare il checkout (e lavorare) su qualsiasi commit. Se si verifica un commit che non è uno dei capi (succursale), ci si trova in una modalità "testa staccata": stackoverflow.com/a/3965714/6309
VonC

1
@Imray Sono d'accordo, ma è così che ho trovato quelle foto 5 anni fa ( nomeesplete.blog/2010/01/28/… )
VonC

11
Per quanto riguarda l'indice, penso che la cosa più utile che si possa dire sia "L'indice è solo un altro nome per l'area di gestione temporanea", come ha detto @ ashraf-alam. Sento che la maggior parte delle volte in discussione viene definita area di gestione temporanea, motivo per cui non ho stabilito automaticamente che fosse la stessa cosa dell'indice.
Pete,

1
@Pete sono d'accordo. Per maggiori informazioni sulla differenza tra la cache e l'indice, vedere la mia altra risposta stackoverflow.com/a/6718135/6309
VonC

137

La differenza tra HEAD (ramo corrente o ultimo stato di commit sul ramo corrente), indice (aka area di gestione temporanea) e albero di lavoro (lo stato dei file in checkout) è descritto nella sezione "I tre stati" della sezione "1.3 Git Basics " capitolo del libro Pro Git di Scott Chacon (licenza Creative Commons).

Ecco l'immagine che lo illustra da questo capitolo:

Operazioni locali - directory di lavoro vs. area di gestione temporanea (indice) vs repository git (HEAD)

Nell'immagine sopra "directory di lavoro" è la stessa di "albero di lavoro", "area di gestione temporanea" è un nome alternativo per git "indice" e HEAD punta al ramo attualmente estratto, che punta punta all'ultimo commit nel " directory git (repository) "

Si noti che git commit -ametterebbe in scena le modifiche e si impegnerebbe in un solo passaggio.


1
"Un'immagine vale più di mille parole". Grazie Jakub .. E grazie per il link.
Joyce Babu,

5
Nota: working treesembra essere preferito ai working directorygiorni nostri. Vedi github.com/git/git/commit/…
VonC

3
Questa immagine non è esattamente precisa perché l'area di gestione temporanea è contenuta in un singolo file chiamato "indice" - e quel file di indice si trova nella directory principale della directory .git. Pertanto, se si definisce il repository come directory .git, l'area di gestione temporanea si trova tecnicamente all'interno del repository. La terza colonna sarebbe meglio etichettata "Oggetto dell'albero radice di HEAD" per indicare che i file estratti sono provenienti da un oggetto commit e che il commit scrive un nuovo albero su un oggetto commit - entrambi gli oggetti commit sono indicati da HEAD.
Jazimov,

@Jazimov Probabilmente hai ragione, ma come ha scritto, ha scattato quella foto dal noto libro Pro Git e ha fornito un link. Quindi, se l'immagine potrebbe essere migliorata o addirittura sbagliata, qualcuno dovrebbe dire agli autori di quel libro ... In generale, sarei disposto a farlo, ma ad essere sincero, sono ancora un principiante e non ho ancora ho capito cosa hai detto, quindi in questo caso sono sicuramente la persona sbagliata.
Binarus,

@Binarus: Il pericolo nella riproduzione all'ingrosso di immagini come questa è che serve a propagare una "travisamento" fatta da un autore / libro. Penso che questo sia un caso di interpretazioni letterali rispetto a interpretazioni funzionali qui: in senso letterale, l'indice in realtà è contenuto nel repository se si definisce il repository come tutto nella cartella .git. In senso funzionale, tuttavia, l'indice aiuta Git a mantenere il DAG nel repository e può essere considerato un essere esterno ad esso.
Jazimov,

64

Il tuo albero di lavoro è ciò che è effettivamente nei file su cui stai attualmente lavorando.

HEADè un puntatore al ramo o al commit che hai estratto l'ultima volta e che sarà il genitore di un nuovo commit se lo esegui. Ad esempio, se ti trovi sul masterramo, allora HEADindicherà master, e quando commetterai, quel nuovo commit sarà un discendente della revisione che ha masterpuntato, e masterverrà aggiornato per puntare al nuovo commit.

L' indice è un'area di gestione temporanea in cui viene preparato il nuovo commit. In sostanza, i contenuti dell'indice sono ciò che andrà nel nuovo commit (anche se git commit -a, in tal caso, questo aggiungerà automaticamente tutte le modifiche ai file che Git conosce sull'indice prima del commit, quindi impegnerà il contenuto corrente dell'albero di lavoro ). git addaggiungerà o aggiornerà i file dall'albero di lavoro nel tuo indice.


Grazie mille per la spiegazione Brian. Pertanto, l'albero di lavoro contiene tutte le modifiche non impegnate. Se eseguo il commit delle mie modifiche con git commit -a, in quel momento specifico il mio albero di lavoro e l'indice saranno gli stessi. Quando invio al mio repository centrale, tutti e tre saranno uguali. Ho ragione?
Joyce Babu,

3
@Vinod Praticamente. Nell'albero di lavoro puoi avere file di cui Git non è a conoscenza e quelli con i quali non ti impegnerai git commit -a(devi aggiungerli con git add), quindi l'albero di lavoro potrebbe avere file extra che il tuo indice, il tuo repository locale o il tuo repository remoto non ha.
Brian Campbell,

2
@Vinod: l'albero di lavoro e l'indice possono diventare gli stessi senza impegnarsi (git add aggiorna l'indice dall'albero di lavoro e git checkout <percorso> aggiorna l'albero di lavoro dall'indice). HEADfa riferimento al commit più recente, quindi quando esegui il commit, stai aggiornando HEADil nuovo commit, che corrisponde all'indice. Il push non ha molto a che fare con esso: crea rami nei rami delle partite remote nel repository locale.
Cascabel,

45

Albero di lavoro

L'albero di lavoro sono i file su cui stai attualmente lavorando.

Indice Git

  • L'indice "git" è dove si posizionano i file che si desidera eseguire il commit nel repository git.

  • L'indice è anche conosciuto come la cache , cache della directory , cache di directory corrente , area di sosta , messo in scena i file .

  • Prima di "eseguire il commit" dei file (checkin) nel repository git, è necessario posizionare i file nell'indice "git".

  • L'indice non è la directory di lavoro: puoi digitare un comando come git status, e git ti dirà quali file nella tua directory di lavoro sono stati aggiunti all'indice git (ad esempio, usando il git add filenamecomando).

  • L'indice non è il repository git: i file nell'indice git sono file che git commetterebbe nel repository git se si usasse il comando git commit.


1
Nota che Git 2.5 porterà più alberi di lavoro ( stackoverflow.com/a/30185564/6309 ). +1
VonC

3
Non sono sicuro che "L'indice non sia la directory di lavoro" sia corretto al 100%. Dovrebbe essere "L'indice non è la directory di lavoro, ma include l'intera directory di lavoro + le modifiche che desideri impegnare successivamente". Prova? vai a un repository git, reset --hard HEADper assicurarti che il tuo indice == il tuo albero di lavoro. an then: mkdir history && git checkout-index --prefix history/ -aIl risultato è una duplicazione dell'intero albero di lavoro nella history/directory. Ergo git index> = directory di lavoro git
Adam Kurkiewicz,

3
L'indice non è la directory di lavoro e non deve includere la directory di lavoro. L'indice è solo un file all'interno del repository git che memorizza informazioni su ciò che si desidera commettere.
Boon,

3
"L'indice" contiene un'istantanea del contenuto dell'albero di lavoro ed è questa istantanea che viene presa come contenuto del prossimo commit. Pertanto, dopo aver apportato modifiche alla directory di lavoro e prima di eseguire il comando commit, necessario utilizzare il comando Add per aggiungere tutti i file nuovi o modificati per l'indice"( git-scm.com/docs/git-add )
anth

3
@AdamKurkiewicz: la prova fallisce se prima echo untracked-data > untracked-file, prima o dopo i passaggi git reset --HARDe git checkout-index. Scoprirai che il file non tracciato non si trova nella historydirectory. Puoi anche modificare sia l'indice che l'albero di lavoro in modo indipendente, sebbene sia difficile modificare l'indice senza prima toccare l'albero di lavoro (richiede l'uso git update-index --index-info).
Torek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.