Das verwirrende Stück ist hier:
Git sieht diese niemals als einzelne Dateien. Git denkt alles als vollen Inhalt.
Git verwendet häufig 160-Bit-Hashes anstelle von Objekten in seinem eigenen Repo. Ein Dateibaum ist im Grunde eine Liste von Namen und Hashes, die dem jeweiligen Inhalt zugeordnet sind (plus einige Metadaten).
Der 160-Bit-Hash identifiziert den Inhalt jedoch eindeutig (innerhalb des Universums der Git-Datenbank). Ein Baum mit Hashes als Inhalt enthält also den Inhalt in seinem Zustand.
Wenn Sie den Status des Inhalts einer Datei ändern, ändert sich ihr Hash. Wenn sich jedoch der Hash ändert, ändert sich auch der mit dem Inhalt des Dateinamens verknüpfte Hash. Was wiederum den Hash des "Verzeichnisbaums" ändert.
Wenn eine Git-Datenbank einen Verzeichnisbaum speichert, impliziert und enthält dieser Verzeichnisbaum den gesamten Inhalt aller Unterverzeichnisse und aller darin enthaltenen Dateien .
Es ist in einer Baumstruktur mit (unveränderlichen, wiederverwendbaren) Zeigern auf Blobs oder andere Bäume organisiert, aber logischerweise ist es eine einzelne Momentaufnahme des gesamten Inhalts des gesamten Baums. Die Darstellung in der Git-Datenbank ist nicht der flache Dateninhalt, sondern logischerweise alle Daten und sonst nichts.
Wenn Sie den Baum in ein Dateisystem serialisiert, alle .git-Ordner gelöscht und git angewiesen haben, den Baum wieder in die Datenbank aufzunehmen, wird der Datenbank am Ende nichts hinzugefügt - das Element wäre bereits vorhanden.
Es kann hilfreich sein, sich Git-Hashes als Referenzzähler auf unveränderliche Daten vorzustellen.
Wenn Sie eine Anwendung darauf erstellt haben, besteht ein Dokument aus mehreren Seiten mit Ebenen, Gruppen und Objekten.
Wenn Sie ein Objekt ändern möchten, müssen Sie eine völlig neue Gruppe dafür erstellen. Wenn Sie eine Gruppe ändern möchten, müssen Sie eine neue Ebene erstellen, für die eine neue Seite und ein neues Dokument erforderlich ist.
Jedes Mal, wenn Sie ein einzelnes Objekt ändern, wird ein neues Dokument erstellt. Das alte Dokument bleibt bestehen. Das neue und das alte Dokument teilen den größten Teil ihres Inhalts - sie haben dieselben Seiten (außer 1). Diese eine Seite hat die gleichen Ebenen (außer 1). Diese Schicht hat die gleichen Gruppen (außer 1). Diese Gruppe hat dieselben Objekte (außer 1).
Und damit meine ich logischerweise eine Kopie, aber in Bezug auf die Implementierung ist es nur ein weiterer Zeiger mit Referenzzählung auf dasselbe unveränderliche Objekt.
Ein Git Repo ist sehr ähnlich.
Dies bedeutet, dass ein bestimmtes Git-Änderungsset seine Festschreibungsnachricht (als Hash-Code), seinen Arbeitsbaum und seine übergeordneten Änderungen enthält.
Diese übergeordneten Änderungen enthalten die übergeordneten Änderungen auf dem gesamten Rückweg.
Der Teil des Git-Repos, der die Geschichte enthält, ist diese Kette von Änderungen. Diese Änderungskette befindet sich auf einer Ebene oberhalb des "Verzeichnis" -Baums. Von einem "Verzeichnis" -Baum aus können Sie nicht eindeutig zu einem Änderungssatz und der Änderungskette gelangen.
Um herauszufinden, was mit einer Datei passiert, beginnen Sie mit dieser Datei in einem Änderungssatz. Dieser Änderungssatz hat eine Geschichte. Oft existiert in diesem Verlauf dieselbe benannte Datei, manchmal mit demselben Inhalt. Wenn der Inhalt identisch ist, wurde die Datei nicht geändert. Wenn es anders ist, gibt es eine Änderung, und es muss gearbeitet werden, um genau herauszufinden, was.
Manchmal ist die Datei weg; Der "Verzeichnis" -Baum enthält jedoch möglicherweise eine andere Datei mit demselben Inhalt (demselben Hash-Code), sodass wir ihn auf diese Weise verfolgen können (Hinweis: Aus diesem Grund möchten Sie, dass ein Commit-to-Move eine von einem Commit-to getrennte Datei verschiebt -bearbeiten). Oder der gleiche Dateiname, und nach dem Überprüfen ist die Datei ähnlich genug.
So kann git einen "Dateiverlauf" zusammenfügen.
Dieser Dateiversionsverlauf stammt jedoch aus dem effizienten Parsen des "gesamten Änderungssatzes" und nicht aus einem Link von einer Version der Datei zu einer anderen.