Was macht git eigentlich, wenn es heißt, dass es „Deltas auflöst“?

187

Während des ersten Klons eines Repositorys empfängt git zuerst die Objekte (was offensichtlich genug ist) und verbringt dann ungefähr die gleiche Zeit damit, "Deltas aufzulösen". Was passiert eigentlich in dieser Phase des Klons?

Nik Reiman
quelle
Siehe auch
Ciro Santilli 法轮功 冠状 病 六四 事件 8
1
Siehe auch für Git 2.20 (Q4 2018) und weitere Delta-Inseln: stackoverflow.com/a/52458712/6309
VonC

Antworten:

54

Git verwendet Delta-Codierung , um einige der Objekte in Packdateien zu speichern. Allerdings wollen Sie nicht jede einzelne Änderung wiedergeben haben jemals auf einer bestimmten Datei, um die aktuelle Version zu erhalten, so Git auch gelegentliche Schnappschüsse der Dateiinhalte gespeichert außerdem hat. "Auflösen von Deltas" ist der Schritt, mit dem sichergestellt wird, dass all dies konsistent bleibt.

Hier ist ein Kapitel aus dem Abschnitt "Git Internals" des Pro Git-Buches, das online verfügbar ist und darüber spricht.

Bernstein
quelle
80
Diese Antwort ist falsch. Es scheint zu beschreiben, wie Mercurial funktioniert, nicht Git. Es wird in der Google-Suche nach diesem Problem angezeigt, daher muss ich antworten. Git ist nicht speichern Sie die Unterschiede zwischen Commits als Delta; Git ist ein "Ganzobjekt" -Speicher. Daher benötigt Git keine "Snapshots", um eine bestimmte Datei anzuzeigen, da der Dateiversionsverlauf nicht aus Deltas rekonstruiert werden muss. So funktioniert Mercurial.
Nexus sagt
12
Der einzige Ort, an dem die Delta-Codierung ins Spiel kommt, ist die Pack-Datei, die ausschließlich der Komprimierung und Übertragung dient. Sie ändert nichts daran, wie Git die Welt "sieht". ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/… ) Eine genaue Antwort finden Sie in der Antwort von araqnid unten.
Nexus sagt
4
Alles, was "Schnappschuss" bedeutet, ist in diesem Zusammenhang eine vollständige Kopie eines Dateistatus und keine Delta-codierte Version. Wie Sie bereits erwähnt haben, verwendet Git die Delta-Codierung in Packdateien. Niemand sagte, dass es "verändert, wie Git die Welt sieht"; Bitte hören Sie auf, Ihre eigenen Annahmen zu projizieren.
Amber
2
Ihre Antwort ist immer noch ungenau. "Git hat auch gelegentlich Schnappschüsse des Dateiinhalts gespeichert." -- Das ist nicht richtig. "'Deltas lösen' ist der Schritt, mit dem sichergestellt wird, dass all dies konsistent bleibt." - das ist auch nicht richtig, die Antwort von araqnid unten ist richtig.
Nexus sagt
1
Wie im oben genannten Kapitel beschrieben, speichert Git immer den vollständigen Dateiinhalt der neuesten Version. Frühere Versionen werden als Delta-codierte Dateien gespeichert, wenn es sich um "lose" Dateien handelt. In regelmäßigen Abständen (entweder durch Aufrufen git gcoder wann immer Git dies für erforderlich hält) komprimiert Git alle "losen" Dateien in eine Packdatei, um Platz zu sparen, und eine Indexdatei in dieser Packdatei wird erstellt. Zlib wird also mit einem eigenen Delta-Algorithmus komprimiert, aber Git verwendet Delta-Codierung, um frühere Versionen zu speichern. Da der häufigste und häufigste Zugriff die neueste Version ist, wird diese als Momentaufnahme gespeichert.
BrionS
118

Die Stufen von git clonesind:

  1. Erhalten Sie eine "Pack" -Datei aller Objekte in der Repo-Datenbank
  2. Erstellen Sie eine Indexdatei für das empfangene Paket
  3. Schauen Sie sich die Kopfrevision an (für ein nicht nacktes Repo natürlich)

"Auflösen von Deltas" ist die Meldung, die für die zweite Stufe angezeigt wird, in der die Pack-Datei indiziert wird ("git index-pack").

Pack-Dateien enthalten nicht die tatsächlichen Objekt-IDs, sondern nur den Objektinhalt. Um festzustellen, wie die Objekt-IDs lauten, muss git für jedes Objekt im Paket eine Dekomprimierung + SHA1 durchführen, um die Objekt-ID zu erstellen, die dann in die Indexdatei geschrieben wird.

Ein Objekt in einer Packdatei kann als Delta gespeichert werden, dh als eine Folge von Änderungen, die an einem anderen Objekt vorgenommen werden müssen. In diesem Fall muss git das Basisobjekt abrufen, die Befehle anwenden und das Ergebnis SHA1. Das Basisobjekt selbst muss möglicherweise durch Anwenden einer Folge von Delta-Befehlen abgeleitet werden. (Obwohl im Fall eines Klons das Basisobjekt bereits angetroffen wurde, ist die Anzahl der hergestellten Objekte im Speicher begrenzt.)

Zusammenfassend lässt sich sagen, dass in der Phase "Auflösen von Deltas" die gesamte Repo-Datenbank dekomprimiert und überprüft wird, was nicht überraschend lange dauert. Vermutlich dauert das Dekomprimieren und Berechnen von SHA1s tatsächlich länger als das Anwenden der Delta-Befehle.

Im Falle eines nachfolgenden Abrufs kann die empfangene Packdatei Verweise (als Delta-Objektbasen) auf andere Objekte enthalten, über die der empfangende Git voraussichtlich bereits verfügt. In diesem Fall schreibt der empfangende Git die empfangene Pack-Datei tatsächlich neu, um solche referenzierten Objekte einzuschließen, so dass jede gespeicherte Pack-Datei autark ist. Hier könnte die Meldung "Auflösen von Deltas" entstanden sein.

araqnid
quelle
7
Kann das parallelisiert werden?
Brooksbp
Ist diese Delta-Komprimierung mehr als das Speichern mehrerer Objekte in einem zlib-Datenstrom?
Fuz
1
@FUZxxl Ja, es verwendet einen Algorithmus wie diff oder xdelta, um zwei Blobs zu vergleichen und ein Bearbeitungsskript zu
erstellen
@brooksbp: Nur mit Einschränkungen. Da für Objekte mit der ID 103fa49 möglicherweise df85b51 dekodiert werden muss, ist df85b51 beim Empfang von 103fa49 noch nicht vorhanden (Packdateien werden streng nach sha1-Hashes sortiert). Für alles, was nur auf Dinge verweist, die bereits vorhanden sind, sind die Dinge einfach, aber für alles andere müssen Sie warten, bis es empfangen wird. Und diese Delta-Komprimierung kann verschachtelt sein, sodass 103fa49 möglicherweise 4e9ba42 benötigt, was wiederum 29ad945 benötigt, was wiederum c9e645a benötigt ... Sie erhalten das Bild. [Ja, ich habe bemerkt, dass es> 4 Jahre sind;)]
Bodo Thiesen
2
@brooksbp: Es stellte sich heraus, dass ich mich geirrt habe, die Packdatei muss NICHT nach sha1-Hashes sortiert werden. Außerdem schreibt git beim Schreiben benötigte Objekte vor Objekten, die sie benötigen. Eigentlich sollten Sie es also parallelisieren können. Einziger verbleibender Nachteil: Da Sie nicht wissen, welche Objekte Sie später benötigen, müssen Sie einige immer wieder neu erstellen. Siehe hier: kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen
4

Amber scheint das Objektmodell zu beschreiben, das Mercurial oder ähnliches verwendet. Git speichert nicht jedes Mal die Deltas zwischen nachfolgenden Versionen eines Objekts, sondern vollständige Snapshots des Objekts. Anschließend werden diese Snapshots mithilfe der Delta-Komprimierung komprimiert, wobei versucht wird, gute Deltas zu finden, die verwendet werden können, unabhängig davon, wo in der Historie diese vorhanden sind.

Johan
quelle
5
Git kann zwar lose Objekte speichern, diese werden jedoch nicht immer als solche gespeichert, da die losen Objekte gelöscht und durch gepackte Inhalte ersetzt werden können. Ich glaube nicht, dass Bernsteins Antwort irgendwo etwas über nachfolgende Versionen aussagte.
AlBlue