Soweit ich weiß, hat Git's Blob SHA1-Hash als Dateiname, um die Datei im Repository nicht zu duplizieren.
Wenn Datei A beispielsweise den Inhalt "abc" hat und einen SHA1-Hashwert wie "12345" hat, können die commits / branches, solange sich der Inhalt nicht ändert, auf denselben SHA1 verweisen.
Aber was würde passieren, wenn Datei A auf "def" geändert wird, um SHA-Hash "23456" zu haben? Speichert Git Datei A und modifizierte Datei A (nicht nur der Unterschied, sondern die ganze Datei)?
Das Folgende von 'Git Community Book' beantwortet die meisten meiner Fragen.
Es ist wichtig zu beachten, dass sich dies sehr von den meisten SCM-Systemen unterscheidet, mit denen Sie vertraut sind. Subversion, CVS, Perforce, Mercurial und andere verwenden Delta Storage-Systeme - sie speichern die Unterschiede zwischen einem Commit und dem nächsten. Git tut dies nicht - es speichert einen Schnappschuss dessen, wie alle Dateien in Ihrem Projekt in dieser Baumstruktur bei jedem Commit aussehen. Dies ist ein sehr wichtiges Konzept, um Git zu verstehen.
git speichert Dateien nach Inhalt und nicht nach Diffs. In diesem Beispiel würden also beide Versionen von A ("abc" und "def") in der Objektdatenbank gespeichert.
Es ist besser, ganze Objekte zu speichern, weil es sehr einfach ist, zu sehen, ob zwei Versionen der Datei identisch sind oder nicht, nur durch den Vergleich ihrer SHAs. Sehen Sie im Git-Buch nach, wie die Objekte gespeichert werden. Das funktioniert besser, denn wenn Dateien mit Diffs nachverfolgt werden, müssen Sie den gesamten Verlauf einer Datei rekonstruieren. Einfach in einem zentralisierten System zu tun, aber nicht in einem verteilten System, wo es viele verschiedene Änderungen an einer Datei geben kann.
Git führt das Diff direkt von den Objekten aus.
Eines der Designziele von git ist Geschwindigkeit. Erwägen Sie, Objekte in git als Deltas und nicht als eindeutige Objekte zu speichern.
Wenn Sie jedes eindeutige Blob mit SHA1-Hash speichern, erfordert das Abrufen des Inhalts von diesem SHA1-Hash nur eine feste Berechnung. Wenn Sie mit der Speicherung von Deltas beginnen, müssen Sie das Objekt rekonstruieren und die Berechnung wird nicht mehr festgelegt und kann abhängig von der Implementierung ohne Einschränkung zunehmen.
Eine gute Möglichkeit, das Design zu verstehen, besteht darin, sich ein tatsächliches Repository anzuschauen (Hinweis: E-Mails fehlten):
%Vor%Sie können anhand dieser beiden Befehle sehen, dass ein Commit nur einige Metadaten, einen oder mehrere Eltern und einen Baum enthält. Ein Baum enthält einen oder mehrere Blobs und Bäume.
Wenn Sie das wissen, können Sie damit beginnen, die Komplexität verschiedener Repository-Operationen zu berücksichtigen. Die Spitze einer Verzweigung ist nur ein Zeiger auf einen Commit-Hash. Also, beginnend damit, ist die Auflistung der Geschichte nur eine Frage der Eltern zu durchlaufen. Wenn Sie den Inhalt des Baums auflisten, müssen Sie nur den Baum und alle Teilbäume durchqueren. Das Abrufen des Dateiinhalts erfolgt wie oben beschrieben.
Natürlich gibt es immer einen Kompromiss, und dieses Modell ist ziemlich platzineffizient, bietet jedoch eine automatische Deduplizierung auf Dateiebene, da jede eindeutige Datei nur einmal gespeichert werden muss. Dies wird effektiv durch die Packdatei gemildert. Delta-Speicher (in Svn, etc.) ist platzsparender ohne Komprimierung, aber Git speichert letztlich effizienter.
Zum Vergleichen können Sie sehen, dass Sie beginnen können, indem Sie Baumhashes vergleichen. Wenn sie nicht übereinstimmen, durchlaufen Sie den Baum und vergleichen seine Blobs und Bäume und so weiter. Da das Modell um atomare Commits entworfen wurde, ist eine Datei diff teurer, aber nicht unangemessen.