Wie speichert git Dateien?

225

Ich habe gerade angefangen, Git zu lernen, und dazu habe ich angefangen, das Git-Community-Buch zu lesen. In diesem Buch heißt es, dass SVN und CVS den Unterschied zwischen Dateien speichern und dass Git einen Schnappschuss aller Dateien speichert.

Aber ich habe nicht wirklich verstanden, was sie mit Schnappschuss meinen. Macht git wirklich eine Kopie aller Dateien in jedem Commit, weil ich das aus ihrer Erklärung verstanden habe?

PS: Wenn jemand eine bessere Quelle hat, um Git zu lernen, würde ich es begrüßen.

mteffaha
quelle
20
Hier ist ein brillanter Beitrag , der ausführlich erklärt, wie Git funktioniert. Was Sie suchen, ist wahrscheinlich der § über die Objektdatenbank.
Greg0ire
Ausgezeichneter Artikel, der Links zu anderen großartigen Ressourcen enthält. Ich habe ein paar Stunden lang Spaß damit gehabt.
Mihai
2
Ich fand diesen wirklich schönen Artikel, der Git von innen nach außen beschreibt: maryrosecook.com/blog/post/git-from-the-inside-out
Sumudu

Antworten:

275

Git enthält für jedes Commit eine vollständige Kopie aller Dateien, mit der Ausnahme, dass der Snapshot für den bereits im Git-Repo vorhandenen Inhalt einfach auf diesen Inhalt verweist, anstatt ihn zu duplizieren.
Das bedeutet auch, dass mehrere Dateien mit demselben Inhalt nur einmal gespeichert werden.

Ein Snapshot ist also im Grunde ein Commit, der sich auf den Inhalt einer Verzeichnisstruktur bezieht .

Einige gute Referenzen sind:

Sie teilen Git mit, dass Sie einen Snapshot Ihres Projekts mit dem Befehl git commit speichern möchten, und es zeichnet im Grunde ein Manifest auf, wie alle Dateien in Ihrem Projekt zu diesem Zeitpunkt aussehen

In Übung 12 wird veranschaulicht, wie frühere Schnappschüsse abgerufen werden


Das Progit-Buch enthält die umfassendere Beschreibung eines Schnappschusses:

Der Hauptunterschied zwischen Git und anderen VCS (einschließlich Subversion und Freunde) besteht darin, wie Git über seine Daten denkt.
Konzeptionell speichern die meisten anderen Systeme Informationen als Liste dateibasierter Änderungen. Diese Systeme (CVS, Subversion, Perforce, Bazaar usw.) betrachten die Informationen, die sie speichern, als eine Reihe von Dateien und die Änderungen, die im Laufe der Zeit an jeder Datei vorgenommen wurden

Delta-basiertes VCS

Git denkt oder speichert seine Daten nicht so. Stattdessen betrachtet Git seine Daten eher als eine Reihe von Schnappschüssen eines Mini-Dateisystems.
Jedes Mal, wenn Sie den Status Ihres Projekts in Git festschreiben oder speichern, wird im Grunde genommen ein Bild davon erstellt, wie alle Ihre Dateien in diesem Moment aussehen, und ein Verweis auf diesen Snapshot gespeichert.
Um effizient zu sein, speichert Git die Datei nicht erneut, wenn sie nicht geändert wurde - nur ein Link zu der vorherigen identischen Datei, die bereits gespeichert wurde.
Git denkt über seine Daten eher wie folgt nach:

Schnappschuss-basiertes VCS

Dies ist eine wichtige Unterscheidung zwischen Git und fast allen anderen VCSs. Dadurch überprüft Git fast jeden Aspekt der Versionskontrolle, den die meisten anderen Systeme der vorherigen Generation kopiert haben. Dies macht Git eher zu einem Mini-Dateisystem mit einigen unglaublich leistungsstarken Tools als zu einem VCS.


Jan Hudec fügt diesen wichtigen Kommentar hinzu :

Während dies auf konzeptioneller Ebene wahr und wichtig ist, gilt dies NICHT auf Speicherebene.
Git verwendet Deltas zur Speicherung .
Darüber hinaus ist es effizienter als jedes andere System. Da der Verlauf pro Datei nicht beibehalten wird, wenn eine Delta-Komprimierung durchgeführt werden sollEs wird jeder Blob benötigt, einige Blobs ausgewählt, die wahrscheinlich ähnlich sind (unter Verwendung von Heuristiken, die die engste Annäherung an die vorherige Version und einige andere enthalten), versucht, die Deltas zu generieren und die kleinste auszuwählen. Auf diese Weise kann es (oft abhängig von der Heuristik) andere ähnliche Dateien oder ältere Versionen nutzen, die ähnlicher sind als die vorherigen. Der Parameter "Pack Window" ermöglicht die Handelsleistung für die Delta-Komprimierungsqualität. Die Standardeinstellung (10) liefert im Allgemeinen anständige Ergebnisse. Wenn jedoch der Speicherplatz begrenzt ist oder die Netzwerkübertragung beschleunigt wird, git gc --aggressivewird der Wert 250 verwendet, wodurch die Ausführung sehr langsam wird, jedoch eine zusätzliche Komprimierung für Verlaufsdaten bereitgestellt wird.

VonC
quelle
4
@ JanHudec guter Punkt. Ich habe Ihren Kommentar zur besseren Sichtbarkeit in die Antwort aufgenommen.
VonC
1
Kennt jemand den Informatikbegriff für das Git-ähnliche Speichermuster, auch bekannt als Hash-basierter Wertspeicher? (oder etwas ähnliches)
Joannes Vermorel
34
Im Zusammenhang mit der eigentlichen Frage des OP scheint der erste Absatz wirklich irreführend. Es ist nicht , bis Sie zum letzten Absatz bekommen , dass wir lernen, oh ja, Tatsache Git tut „store [...] Unterschiede zwischen den Dateien. Wirklich , dass Informationen wünschen wurde Top-Liste steht und nicht so tief vergraben. Das heißt, Dank an Zumindest die wahre Geschichte irgendwo in deine Antwort aufnehmen;)
Josh O'Brien
1
@ NickVolynkin Großartig! Ich bin froh, dass diese Antworten ein größeres Publikum finden.
VonC
1
Ein weiteres gutes Buch: Git von unten nach oben: ftp.newartisans.com/pub/git.from.bottom.up.pdf
Jonas Berlin
45

Git speichert jede Datei logisch unter seinem SHA1. Dies bedeutet, dass nur eine Kopie gespeichert wird, wenn Sie zwei Dateien mit genau demselben Inhalt in einem Repository haben (oder wenn Sie eine Datei umbenennen).

Dies bedeutet jedoch auch, dass beim Ändern eines kleinen Teils einer Datei und beim Festschreiben eine weitere Kopie der Datei gespeichert wird. Die Art und Weise, wie Git dies löst, ist die Verwendung von Pack-Dateien. Hin und wieder werden alle „losen“ Dateien (eigentlich nicht nur Dateien, sondern auch Objekte, die Commit- und Verzeichnisinformationen enthalten) aus einem Repo gesammelt und zu einer Packdatei komprimiert. Die Packdatei wird mit zlib komprimiert. Und ähnliche Dateien sind auch deltakomprimiert.

Das gleiche Format wird auch beim Ziehen oder Drücken verwendet (zumindest bei einigen Protokollen), sodass diese Dateien nicht erneut komprimiert werden müssen.

Das Ergebnis ist, dass ein Git-Repository, das die gesamte unkomprimierte Arbeitskopie, unkomprimierte aktuelle Dateien und komprimierte ältere Dateien enthält, normalerweise relativ klein ist, zweimal kleiner als die Größe der Arbeitskopie. Dies bedeutet, dass es kleiner als SVN-Repo mit denselben Dateien ist, obwohl SVN den Verlauf nicht lokal speichert.

svick
quelle
1
ah so mercurial ist platzsparender
Ben