Dies ist eine unvermeidlich lange, aber leicht verständliche Erklärung von ProGit-Buch :
Git als System verwaltet und manipuliert in seinem normalen Betrieb drei Bäume:
- KOPF: Schnappschuss der letzten Übergabe, nächste übergeordnete Übergabe
- Index: Vorgeschlagener nächster Commit-Snapshot
- Arbeitsverzeichnis: Sandkasten
Der HEAD
HEAD ist die Zeiger zum Referenz der aktuellen Verzweigung , der wiederum ein Zeiger auf den letzte Übergabe in diesem Zweig . Das bedeutet, dass HEAD die Elternteil der nächsten Übergabe, die erstellt wird . Im Allgemeinen ist es am einfachsten, sich HEAD als die Schnappschuss der letzten Übertragung in diesem Zweig .
Was enthält sie?
Um zu sehen, wie dieser Snapshot aussieht, führen Sie Folgendes im Root-Verzeichnis Ihres Repositorys aus:
git ls-tree -r HEAD
würde dies in etwa zu folgendem Ergebnis führen:
$ git ls-tree -r HEAD
100644 blob a906cb2a4a904a152... README
100644 blob 8f94139338f9404f2... Rakefile
040000 tree 99f1a6d12cb4b6f19... lib
Der Index
Git füllt diesen Index mit einer Liste aller Dateiinhalte, die zuletzt in Ihr Arbeitsverzeichnis ausgecheckt wurden und wie sie aussahen, als sie ursprünglich ausgecheckt wurden. Anschließend ersetzen Sie einige dieser Dateien durch neue Versionen, und Git Commit wandelt diese in den Baum für eine neue Übertragung um.
Was enthält sie?
Verwenden Sie git ls-files -s
um zu sehen, wie es aussieht. Sie sollten etwa so etwas sehen:
100644 a906cb2a4a904a152e80877d4088654daad0c859 0 README
100644 8f94139338f9404f26296befa88755fc2598c289 0 Rakefile
100644 47c6340d6459e05787f644c2447d2595f5d3a54b 0 lib/simplegit.rb
Das Arbeitsverzeichnis
Hier befinden sich Ihre Dateien und Sie können Änderungen ausprobieren, bevor Sie sie in den Staging-Bereich (Index) und dann in den Verlauf übertragen.
Visualisierte Probe
Schauen wir uns an, wie diese drei Bäume (wie sie im ProGit-Buch genannt werden) zusammenarbeiten.
Der typische Arbeitsablauf von Git besteht darin, Schnappschüsse Ihres Projekts in immer besseren Zuständen aufzuzeichnen, indem Sie diese drei Bäume manipulieren. Werfen Sie einen Blick auf dieses Bild:
Um ein gutes visuelles Verständnis zu erhalten, betrachten Sie folgendes Szenario. Nehmen wir an, Sie gehen in ein neues Verzeichnis mit einer einzigen Datei darin. Nennen Sie dies v1 der Datei. Sie ist in blau dargestellt. Ausführen von git init
erstellt ein Git-Repository mit einer HEAD-Referenz, die auf den ungeborenen Master-Zweig verweist
Zu diesem Zeitpunkt hat nur der Arbeitsverzeichnisbaum einen Inhalt. Jetzt wollen wir diese Datei übertragen, also benutzen wir git add
um den Inhalt des Arbeitsverzeichnisses in den Index zu kopieren.
Dann führen wir git commit
der den Inhalt des Index als permanenten Snapshot speichert, ein Commit-Objekt erzeugt, das auf diesen Snapshot verweist, und den Master so aktualisiert, dass er auf diesen Commit verweist.
Wenn wir die git status
wir werden sehen keine Änderungen denn alle drei Bäume sind identisch .
Der schöne Punkt
git status zeigt den Unterschied zwischen diesen Bäumen auf folgende Weise an:
- Wenn der Arbeitsbaum nicht mit dem Index übereinstimmt, dann
git status
wird zeigen es gibt einige Änderungen, die nicht für die Übergabe vorgesehen sind
- Wenn der Arbeitsbaum mit dem Index übereinstimmt, aber nicht mit HEAD übereinstimmt, dann
git status
zeigt einige Dateien unter zu übernehmende Änderungen Abschnitt in seinem Ergebnis
- Wenn der Arbeitsbaum nicht mit dem Index übereinstimmt, und index nicht mit HEAD übereinstimmt, dann
git status
zeigt einige Dateien unter Änderungen, die nicht für die Übertragung vorgesehen sind Abschnitt und einige andere Dateien unter zu übernehmende Änderungen Abschnitt in seinem Ergebnis.
Für die ganz Neugierigen
Hinweis zu git reset
Befehl
Wir hoffen, dass wir wissen, wie reset
Die Kommandoarbeiten werden den Grund für die Existenz dieser drei Bäume weiter erhellen.
reset
ist die Zeitmaschine in Git, mit der Sie leicht in der Zeit zurückgehen und einige alte Schnappschüsse für die Arbeit mitbringen können. Auf diese Weise ist HEAD das Wurmloch, durch das Sie in der Zeit reisen können. Sehen wir uns an einem Beispiel aus dem Buch an, wie das funktioniert:
Betrachten Sie das folgende Repository mit einer einzigen Datei und 3 Commits, die in verschiedenen Farben und mit unterschiedlichen Versionsnummern angezeigt werden:
Der Zustand der Bäume ist wie auf dem nächsten Bild zu sehen:
Schritt 1: Verschieben von HEAD (--soft):
Beim Zurücksetzen wird zunächst der Verweis auf HEAD verschoben. Dies ist nicht dasselbe wie das Ändern von HEAD selbst (was mit checkout geschieht). reset verschiebt den Zweig, auf den HEAD verweist. Das heißt, wenn HEAD auf den Master-Zweig gesetzt ist, wird durch den Aufruf von git reset 9e5e6a4 der Master-Zweig auf 9e5e6a4 verweisen. Wenn Sie reset
mit --soft
Option wird es hier enden, ohne dass die index
y working directory
. Unser Repo sieht jetzt wie folgt aus:
Hinweis: HEAD~ ist der Elternteil von HEAD
Wenn wir uns das Bild ein zweites Mal ansehen, können wir erkennen, dass der Befehl im Wesentlichen die letzte Übertragung rückgängig gemacht hat. Da der Arbeitsbaum und der Index derselbe sind, sich aber von HEAD unterscheiden, git status
zeigt nun die Änderungen in grüner Farbe an, damit sie übertragen werden können.
Schritt 2: Aktualisierung des Index (--mixed):
Dies ist die Standardoption des Befehls
Laufen reset
avec --mixed
aktualisiert den Index mit dem Inhalt des Snapshots, auf den HEAD gerade verweist, wobei das Arbeitsverzeichnis intakt bleibt. Auf diese Weise sieht Ihr Projektarchiv so aus, als hätten Sie eine Arbeit durchgeführt, die nicht in den Stages enthalten ist und git status
zeigt dies als Änderungen, die nicht für die Übergabe vorgesehen sind, in Rot an. Diese Option macht auch die letzte Übergabe rückgängig und hebt die Bereitstellung aller Änderungen auf. Es ist, als hätten Sie Änderungen vorgenommen, aber nicht die Option git add
Befehl noch nicht. Unser Repo würde jetzt wie folgt aussehen:
Schritt 3: Aktualisieren des Arbeitsverzeichnisses (--hard)
Wenn Sie anrufen reset
avec --hard
wird der Inhalt des Schnappschusses, auf den HEAD verweist, in HEAD, index und Arbeitsverzeichnis kopiert. Nach der Ausführung des Befehls reset --hard würde dies bedeuten, dass Sie zu einem früheren Zeitpunkt zurückgekehrt sind und danach nichts mehr getan haben, siehe das folgende Bild:
Schlussfolgerung
Ich hoffe, Sie haben jetzt ein besseres Verständnis für diese Bäume und eine Vorstellung davon, welche Möglichkeiten sie Ihnen bieten, indem sie es Ihnen ermöglichen, Ihre Dateien in Ihrem Repository zu ändern und Dinge rückgängig zu machen oder wiederherzustellen, die Sie versehentlich getan haben.
40 Stimmen
In Bezug auf Ihre Bearbeitung: absolut nicht.
HEAD
ist die Übergabe an der Spitze des aktuellen Zweigs. Wenn Sie den Zweig gerade ausgecheckt haben, d.h. keine Dateien geändert haben, dann stimmt sein Inhalt mit dem Arbeitsbaum überein. Sobald Sie etwas ändern, stimmt er nicht mehr überein.13 Stimmen
Ich glaube, Sie müssen das lesen: denke-wie-ein-git.net
9 Stimmen
Ich würde auch eine
Staging Area
zu dieser Liste hinzufügen. Was istHEAD
,Working Tree
,Index
und eineStaging Area
7 Stimmen
Der letzte Satz von @Jefromi wäre klarer als dieser: > Sobald Sie etwas ändern, stimmt der Arbeitsbaum nicht mehr mit dem HEAD-Commit überein.
4 Stimmen
Für alle, die dies in Zukunft lesen, ist der beste Weg, einige dieser Antworten wirklich zu verstehen, zu sehen und zu fühlen und visuell zu begreifen, was vor sich geht: Dies ist das beste Werkzeug, um Git überhaupt zu lernen: onlywei.github.io/explain-git-with-d3/#fetchrebase
5 Stimmen
@Green: Staging Area und Index sind ein und dasselbe. (Siehe genehmigte Antwort unten)
0 Stimmen
@BKSpurgeon Keiner der Links bringt etwas.
0 Stimmen
@DrEval Versuchen Sie, auf die Schaltfläche "Aktualisieren" zu klicken, und die Grafiken sollten geladen werden.
1 Stimmen
HEAD ist in der Regel (wenn nicht abgetrennt) ein Verweis auf den letzten Commit auf einem Zweig und nicht ein Commit selbst. Man sollte aber auch hinzufügen, dass ein Zweig selbst ein Zeiger auf einen Commit ist, genau wie HEAD. Der Zeiger ist nur ein Bezeichner, der die Commit-ID darstellt.