Was ist der Unterschied zwischen HEAD, Arbeitsbaum und Index in Git?

488

Kann mir jemand den Unterschied zwischen HEAD, Arbeitsbaum und Index in Git erklären?

Soweit ich weiß, sind sie alle Namen für verschiedene Zweige. Ist meine Annahme richtig?


Bearbeiten

ich habe das gefunden

Ein einzelnes Git-Repository kann eine beliebige Anzahl von Zweigen verfolgen, aber Ihr Arbeitsbaum ist nur einem von ihnen zugeordnet (dem "aktuellen" oder "ausgecheckten" Zweig), und HEAD zeigt auf diesen Zweig.

Bedeutet dies, dass KOPF und Arbeitsbaum immer gleich sind?

Joyce Babu
quelle
26
In Bezug auf Ihre Bearbeitung: absolut nicht. HEADist das Commit an der Spitze des aktuellen Zweigs. Wenn Sie gerade den Zweig ausgecheckt haben, dh keine geänderten Dateien haben, stimmt sein Inhalt mit dem Arbeitsbaum überein. Sobald Sie etwas ändern, stimmt es nicht mehr überein.
Cascabel
6
Ich denke, Sie müssen dies lesen: think-like-a-git.net
Andrzej Duś
5
Ich würde Staging Areadieser Liste auch eine hinzufügen . Was ist HEAD, Working Tree, IndexundStaging Area
Grün
2
Der letzte Satz von @ Jefromi's wäre klarer als:> Sobald Sie etwas ändern, stimmt der Arbeitsbaum nicht mehr mit dem HEAD-Commit
überein
3
Wenn Sie dies in Zukunft lesen möchten,
BKSpurgeon

Antworten:

579

Einige andere gute Referenzen zu diesen Themen:

Alt-Text

Ich benutze den Index als Kontrollpunkt .

Wenn ich im Begriff bin, eine Änderung vorzunehmen, die möglicherweise schief geht - wenn ich eine Richtung erkunden möchte, in der ich nicht sicher bin, ob ich sie durchsetzen kann oder ob es eine gute Idee ist, z. B. eine konzeptionell anspruchsvolle Umgestaltung oder Änderung einer Darstellungstyp - Ich überprüfe meine Arbeit im Index. Wenn dies die erste Änderung ist, die ich seit meinem letzten Festschreiben vorgenommen habe, kann ich das lokale Repository als Prüfpunkt verwenden, aber häufig habe ich eine konzeptionelle Änderung, die ich als eine Reihe kleiner Schritte implementiere. Ich möchte nach jedem Schritt einen Checkpoint erstellen, aber das Commit speichern, bis ich wieder mit dem funktionierenden, getesteten Code fertig bin.

Anmerkungen:

  1. Der Arbeitsbereich ist der Verzeichnisbaum der (Quell-) Dateien, die Sie sehen und bearbeiten.

  2. Der Index ist eine einzelne, große Binärdatei, in <baseOfRepo>/.git/indexder alle Dateien im aktuellen Zweig, ihre sha1- Prüfsummen, Zeitstempel und der Dateiname aufgelistet sind. Es handelt sich nicht um ein anderes Verzeichnis mit einer Kopie der Dateien.

  3. Das lokale Repository ist ein verstecktes Verzeichnis ( .git), das ein objectsVerzeichnis enthält, das alle Versionen jeder Datei im Repo (lokale Zweige und Kopien von entfernten Zweigen) als komprimierte "Blob" -Datei enthält.

Stellen Sie sich die vier im obigen Bild dargestellten "Datenträger" nicht als separate Kopien der Repo-Dateien vor.

Alt-Text

Sie werden grundsätzlich als Referenzen für Git-Commits bezeichnet. Es gibt zwei Haupttypen von Refs: Tags und Köpfe.

  • Tags sind feste Referenzen, die einen bestimmten Punkt im Verlauf markieren, z. B. Version 2.6.29.
  • Im Gegenteil, die Köpfe werden immer bewegt, um die aktuelle Position der Projektentwicklung widerzuspiegeln.

Alt-Text

(Anmerkung: wie kommentiert von Timo Huovinen , diese Pfeile sind nicht das, was die Commits zeigen auf, es ist die Workflow - Reihenfolge , im Grunde zeigt Pfeile , wie , 1 -> 2 -> 3 -> 4wo 1der erste begehen und 4ist die letzte)

Jetzt wissen wir, was im Projekt passiert.
Aber um zu wissen, was genau hier passiert, gibt es gerade eine spezielle Referenz namens HEAD. Es dient zwei Hauptzwecken:

  • Es teilt Git mit, von welchem ​​Commit Dateien beim Auschecken übernommen werden sollen
  • Es teilt Git mit, wo beim Festschreiben neue Commits abgelegt werden sollen.

Wenn Sie es ausführen, zeigt git checkout refes HEADauf die von Ihnen angegebene Referenz und extrahiert Dateien daraus. Wenn Sie es ausführen git commit, wird ein neues Festschreibungsobjekt erstellt, das dem aktuellen Objekt untergeordnet wird HEAD. Zeigt normalerweise HEADauf einen der Köpfe, sodass alles gut funktioniert.

Alt-Text

VonC
quelle
20
Nachdem ich viele Male über Git gelesen habe, verstehe ich es nie ganz. Ich war wirklich frustriert und möchte das Wort f verwenden. Aber ich bin in der Gemeinschaft! Du hast Köpfe erwähnt, aber in den Bildern oben gibt es immer einen einzigen KOPF, wo die restlichen Köpfe sind? "Normalerweise zeigt HEAD auf einen der Köpfe, also funktioniert alles einwandfrei." Ich bitte dich, das zu erklären, Ur Aussage.
Necktwi
12
@neckTwi HEAD ist das aktuelle Commit, mit dem Sie arbeiten ( stackoverflow.com/a/964927/6309 ). Es ist normalerweise einer der "Zweigköpfe" (einer der durch Zweige referenzierten Commits, die die Spitze dieser Zweige darstellen). Sie können jedoch jedes Commit auschecken (und bearbeiten). Wenn Sie ein Commit auschecken
VonC
1
@Imray Ich stimme zu, aber so habe ich diese Bilder vor 5 Jahren gefunden ( hades.name/blog/2010/01/28/… )
VonC
11
In Bezug auf den Index denke ich, dass das Nützlichste, was gesagt werden kann, "Der Index ist nur ein anderer Name für den Bereitstellungsbereich" ist, wie @ ashraf-alam sagte. Ich habe das Gefühl, dass es die meiste Zeit in der Diskussion als Staging-Bereich bezeichnet wird, weshalb ich nicht automatisch die Verbindung hergestellt habe, dass es dasselbe ist wie der Index.
Pete
1
@ Pete Ich stimme zu. Weitere Informationen
VonC
137

Der Unterschied zwischen HEAD (aktueller Zweig oder letzter festgeschriebener Status im aktuellen Zweig), Index (auch bekannt als Staging-Bereich) und Arbeitsbaum (Status der Dateien beim Auschecken) wird im Abschnitt "Die drei Status " der "1.3 Git-Grundlagen " beschrieben. Kapitel des Pro Git- Buches von Scott Chacon (Creative Commons lizenziert).

Hier ist das Bild aus diesem Kapitel:

Lokale Operationen - Arbeitsverzeichnis vs. Staging-Bereich (Index) vs. Git-Repository (HEAD)

Im obigen Bild ist "Arbeitsverzeichnis" dasselbe wie "Arbeitsbaum", der "Bereitstellungsbereich" ist ein alternativer Name für "git" -Git, und HEAD zeigt auf den aktuell ausgecheckten Zweig, dessen Tipp auf das letzte Festschreiben im "Arbeitsverzeichnis" verweist. Git-Verzeichnis (Repository) "

Beachten Sie, dass git commit -aÄnderungen vorgenommen und in einem Schritt festgeschrieben werden.

Jakub Narębski
quelle
1
"Ein Bild sagt mehr als tausend Worte". Danke Jakub .. Und danke für den Link.
Joyce Babu
5
Hinweis: working treescheint working directoryheutzutage vorzuziehen zu sein . Siehe github.com/git/git/commit/…
VonC
3
Dieses Bild ist nicht genau, da der Staging-Bereich in einer einzelnen Datei namens "index" enthalten ist - und diese Indexdatei sich zufällig im Stammverzeichnis des .git-Verzeichnisses befindet. Wenn Sie also das Repo als .git-Verzeichnis definieren, befindet sich der Staging-Bereich technisch im Repo. Die dritte Spalte ist besser mit "HEADs Stammbaumobjekt" gekennzeichnet, um anzuzeigen, dass die ausgecheckten Dateien von einem Festschreibungsobjekt stammen und dass beim Festschreiben ein neuer Baum in ein Festschreibungsobjekt geschrieben wird. Auf beide Festschreibungsobjekte wird von HEAD verwiesen.
Jazimov
@Jazimov Sie haben wahrscheinlich Recht, aber wie er schrieb, hat er dieses Bild aus dem bekannten Pro Git-Buch genommen und einen Link bereitgestellt. Wenn also das Bild verbessert werden könnte oder sogar falsch ist, sollte jemand den Autoren dieses Buches davon erzählen ... Im Allgemeinen wäre ich dazu bereit, aber um ehrlich zu sein, ich bin immer noch ein Git-Anfänger und habe es noch nicht getan Ich habe verstanden, was Sie gesagt haben, also bin ich in diesem Fall definitiv die falsche Person.
Binarus
@Binarus: Die Gefahr bei der Großreproduktion solcher Bilder besteht darin, dass sie dazu dienen, eine "falsche Darstellung" eines Autors / Buches zu verbreiten. Ich denke, dies ist hier ein Fall von wörtlichen versus funktionalen Interpretationen: Im wörtlichen Sinne ist der Index tatsächlich im Repo enthalten, wenn Sie das Repo als alles unter dem Ordner .git definieren. Im funktionalen Sinne hilft der Index Git jedoch dabei, die DAG im Repo zu halten, und man kann sich vorstellen, dass es sich um ein externes Wesen handelt.
Jazimov
64

Ihr Arbeitsbaum befindet sich tatsächlich in den Dateien, an denen Sie gerade arbeiten.

HEADist ein Zeiger auf den Zweig oder das Commit, das Sie zuletzt ausgecheckt haben und der das übergeordnete Element eines neuen Commits ist, wenn Sie es ausführen. Wenn Sie sich beispielsweise in der masterVerzweigung befinden, HEADwird auf masterdieses neue Festschreiben masterverwiesen , und wenn Sie es festschreiben, ist es ein Nachkomme der Revision, auf die verwiesen wurde, und masterwird aktualisiert, um auf das neue Festschreiben zu verweisen.

Der Index ist ein Staging-Bereich, in dem das neue Commit vorbereitet wird. Im Wesentlichen wird der Inhalt des Index in das neue Commit aufgenommen. Wenn Sie dies jedoch tun git commit -a, werden automatisch alle Änderungen an Dateien, die Git kennt, vor dem Commit zum Index hinzugefügt, sodass der aktuelle Inhalt Ihres Arbeitsbaums festgeschrieben wird ). git addfügt Dateien aus dem Arbeitsbaum zu Ihrem Index hinzu oder aktualisiert sie.

Brian Campbell
quelle
Vielen Dank für die Erklärung Brian. Der Arbeitsbaum enthält also alle nicht festgeschriebenen Änderungen. Wenn ich meine Änderungen mit git commit -a festschreibe, sind mein Arbeitsbaum und mein Index zu diesem bestimmten Zeitpunkt identisch. Wenn ich zu meinem zentralen Repo gehe, sind alle drei gleich. Hab ich recht?
Joyce Babu
3
@ Vinod Ziemlich viel. Sie können Dateien in Ihrem Arbeitsbaum haben, von denen Git nichts weiß, und diese werden nicht festgeschrieben git commit -a(Sie müssen sie hinzufügen git add), sodass Ihr Arbeitsbaum möglicherweise zusätzliche Dateien enthält, die Ihr Index, Ihr lokales Repo oder Ihr Remote-Repo hat nicht.
Brian Campbell
2
@Vinod: Der Arbeitsbaum und der Index können ohne Festschreiben identisch werden (git add aktualisiert den Index aus dem Arbeitsbaum und git checkout <Pfad> aktualisiert den Arbeitsbaum aus dem Index). HEADbezieht sich auf das letzte Festschreiben. Wenn Sie also festschreiben, aktualisieren Sie HEADauf Ihr neues Festschreiben, das dem Index entspricht. Pushing hat nicht viel damit zu tun - es werden Zweige in den Remote-Match-Zweigen in Ihrem lokalen Repo erstellt.
Cascabel
45

Arbeitsbaum

Ihr Arbeitsbaum sind die Dateien, an denen Sie gerade arbeiten.

Git-Index

  • Im Git "Index" platzieren Sie Dateien, die Sie in das Git-Repository übertragen möchten.

  • Der Index wird auch als Cache , Verzeichnis-Cache , aktueller Verzeichnis-Cache , Staging-Bereich und bereitgestellte Dateien bezeichnet .

  • Bevor Sie Dateien in das Git-Repository "festschreiben" (einchecken), müssen Sie zuerst die Dateien in den Git-Index "einfügen".

  • Der Index ist nicht das Arbeitsverzeichnis: Sie können einen Befehl wie git statuseingeben, und git teilt Ihnen mit, welche Dateien in Ihrem Arbeitsverzeichnis zum git-Index hinzugefügt wurden (z. B. mithilfe des git add filenameBefehls).

  • Der Index ist nicht das Git-Repository: Dateien im Git-Index sind Dateien, die Git in das Git-Repository festschreiben würde, wenn Sie den Befehl git commit verwenden würden.

Ashraf Alam
quelle
1
Beachten Sie, dass Git 2.5 mehrere Arbeitsbäume bringt ( stackoverflow.com/a/30185564/6309 ). +1
VonC
3
Ich bin nicht sicher, ob "Der Index ist nicht das Arbeitsverzeichnis" 100% korrekt ist. Es sollte "Der Index ist nicht das Arbeitsverzeichnis, aber es enthält das gesamte Arbeitsverzeichnis + Änderungen, die Sie als nächstes festschreiben möchten" sein. Beweis? Gehen Sie zu einem Git-Repository, reset --hard HEADum sicherzustellen, dass Ihr Index == Ihr Arbeitsbaum ist. und dann: mkdir history && git checkout-index --prefix history/ -aDas Ergebnis ist eine Verdoppelung Ihres gesamten Arbeitsbaums in Ihrem history/Verzeichnis. Ergo Git Index> = Git Arbeitsverzeichnis
Adam Kurkiewicz
3
Index ist nicht das Arbeitsverzeichnis und muss das Arbeitsverzeichnis nicht enthalten. Index ist nur eine Datei im Git-Repository, in der Informationen gespeichert sind, die Sie festschreiben möchten.
Boon
3
"Der" Index "enthält eine Momentaufnahme des Inhalts des Arbeitsbaums. Diese Momentaufnahme wird als Inhalt des nächsten Commits verwendet. Nachdem Sie also Änderungen am Arbeitsverzeichnis vorgenommen und den Commit-Befehl ausgeführt haben, müssen Sie muss den Befehl add verwenden, um neue oder geänderte Dateien zum Index hinzuzufügen "( git-scm.com/docs/git-add )
anth
3
@AdamKurkiewicz: Der Beweis schlägt fehl, wenn Sie zuerst echo untracked-data > untracked-file, vor oder nach dem git reset --HARDund git checkout-indexSchritte. Sie werden feststellen, dass sich die nicht verfolgte Datei nicht im historyVerzeichnis befindet. Sie können sowohl den Index als auch den Arbeitsbaum unabhängig voneinander ändern, obwohl das Ändern des Index ohne vorheriges Berühren des Arbeitsbaums schwierig ist (erfordert die Verwendung git update-index --index-info).
Torek