Was bedeuten die Zahlen in der „Total“-Zeile der Ausgabe von git gc/git repack?

Lesezeit: 6 Minuten

Benutzer-Avatar
ich und

Wenn ich laufe git gc oder git repack über mein Git-Repository gibt es eine “Total” -Zeile aus, sobald es fertig ist. Was bedeuten diese Zahlen?

Ein paar Beispiele aus einem ziemlich kleinen Repository:

$ git gc
...
Total 576 (delta 315), reused 576 (delta 315)

$ git repack -afd --depth=250 --window=250
...
Total 576 (delta 334), reused 242 (delta 0)

Und eine aus einem viel größeren Repository:

$ git gc
...
Total 347629 (delta 289610), reused 342219 (delta 285060)
...

Ich kann erraten, was diese erste “Gesamtzahl” ist: die Anzahl der Git-Objekte (also Commits, Bäume und Dateien) im Repository. Was bedeuten eigentlich alle anderen?

Die habe ich mir schon angeschaut git-gc(1) und git-repack(1) Manpages gelesen und auch ihre “Siehe auch”-Seiten gelesen, und meine Versuche zu googeln haben nur irrelevante Ergebnisse geliefert.

  • github.com/git/git/blob/master/builtin/pack-objects.c

    – Josh Lee

    21. Februar 2012 um 15:08 Uhr


  • @JoshLee Ich habe mir (jetzt) ​​kurz den Code angesehen und kann nicht leicht herausfinden, was los ist. Danke aber für den Hinweis 🙂

    – ich und

    22. Februar 2012 um 10:04 Uhr

Benutzer-Avatar
Niall Douglas

Ich habe etwas mit gearbeitet dulwich, eine reine Python-Implementierung von Git. Was ich hier sagen werde, spiegelt meine Erfahrung mit der Git-Implementierung von Dulwich wider, nicht mit der kanonischen Git-Quelle, und daher kann es Unterschiede geben.

Git ist bemerkenswert einfach – ich meine, so einfach, dass es verwirrt! Der Name passt wirklich zu seinem Design, das aufgrund seiner Dummheit sehr clever ist.

Wenn Sie irgendetwas festschreiben, nimmt git den Inhalt des Index (Staging-Bereich) und erstellt SHA-Digest-Elemente, sodass jede Datei SHA- und die Dateien in jedem Verzeichnis als Blob-Objekte SHA- und natürlich die Verzeichnisstruktur als Baumobjekte SHA- und all das wird in ein Commit-Objekt eingebunden, das auch einen SHA hat. Git feuert diese einfach direkt in das Ablagesystem in .git/objects, während es den Commit verarbeitet. Wenn es gelingt, alle dort hineinzufeuern, schreibt es einfach den SHA des neuesten Commit-Objekts in .git/refs/heads/.

Von Zeit zu Zeit kann ein Commit auf halbem Weg fehlschlagen. Wenn etwas nicht in .git/objects geschrieben werden kann, git führt zu diesem Zeitpunkt keine Bereinigung durch. Das liegt daran, dass Sie normalerweise das Problem beheben und das Commit wiederholen – in diesem Fall wird Git genau dort neu starten, wo es zuvor angehalten wurde, dh auf halbem Weg durch das Commit.

Hier kommt git gc ins Spiel. Es durchsucht einfach alle Objekte in .git/objects und markiert alle Objekte, auf die in irgendeiner Weise durch einen HEAD oder einen BRANCH verwiesen wird. Alles, was offensichtlich übrig bleibt, ist verwaist und hat nichts mit irgendetwas “Wichtigem” zu tun, also kann es gelöscht werden. Aus diesem Grund wird, wenn Sie verzweigen, etwas an diesem Zweig arbeiten, diesen Zweig aber später aufgeben und alle Verweise darauf aus Ihrem Git-Repo löschen, das periodische git gc, das ausgeführt wird, Ihren Zweig vollständig bereinigen. Dies kann einige ältere VCS-Benutzer überraschen, z. B. vergaß CVS nie etwas, außer wenn es abstürzte oder sich selbst beschädigte (was oft der Fall war).

git repack (eigentlich git-pack-objects) unterscheidet sich völlig von git gc (wie in einem separaten Befehl und Vorgang, obwohl git gc git repack aufrufen kann). Wie ich bereits erwähnt habe, feuert git einfach alles in seine eigene SHAed-Datei. Es komprimiert sie, bevor es in den Plattenspeicher geht, aber offensichtlich ist das auf lange Sicht nicht platzsparend. Was also git-pack-objects tut, ist eine Reihe von SHA-Objekten auf überall hin zu untersuchen, wo Daten über Revisionen hinweg repliziert werden. Es spielt keine Rolle, um welche Art von SHA-Objekt es sich handelt – alle werden beim Packen als gleich angesehen. Es generiert dann binäre Deltas, wo diese sinnvoll sind, und speichert das gesamte Los als .pack-Datei in .git/objects/pack, wobei alle gepackten Objekte aus der normalen Verzeichnisstruktur entfernt werden.

Beachten Sie, dass git-pack-objects im Allgemeinen eine neue .pack-Datei erstellt, anstatt vorhandene .pack-Dateien zu ersetzen, wenn die neueste Pack-Datei weniger als 1 MB groß ist. Daher werden Sie im Laufe der Zeit mehrere .pack-Dateien in .git/objects/pack sehen. Wenn Sie git fetch ausführen, bitten Sie das entfernte Repo einfach, alle entpackten Elemente zu packen und die .pack-Dateien, die das abrufende Repo nicht benötigt, an das abrufende Repo zu senden. git repack ruft einfach git-pack-objects auf, weist es aber an, .pack-Dateien nach eigenem Ermessen zusammenzuführen. Das bedeutet, alles zu dekomprimieren, was sich geändert hat, die binären Deltas neu zu generieren und erneut zu komprimieren.

Um Ihre Frage zu beantworten, bezieht sich die Gesamtzeile auf die Gesamtzahl der Objekte im Git-Repo. Die erste Delta-Zahl ist die Anzahl der gesamten Objekte, die binäre Delta-Objekte sind, dh wie viele Objekte git entschieden hat, dass sie eine starke Ähnlichkeit mit anderen Objekten haben und als binäres Delta gespeichert werden können. Die wiederverwendete Zahl gibt an, wie viele Objekte aus einer komprimierten Quelle (dh einer Packdatei) verwendet werden, ohne erneut komprimiert worden zu sein, um neuere Änderungen aufzunehmen. Dies würde auftreten, wenn Sie mehrere Packfiles haben, aber ein neueres SHA-Objekt auf ein Element in einer alten Packfile als Basis verweist und dann Deltas darauf anwendet, um es modern zu machen. Dadurch kann git zuvor komprimierte ältere Revisionen von Daten verwenden, ohne sie erneut komprimieren zu müssen, um neuere Ergänzungen aufzunehmen. Beachten Sie, dass git an eine vorhandene Paketdatei anhängen kann, ohne die gesamte Paketdatei neu zu schreiben.

Im Allgemeinen zeigt eine hohe Wiederverwendungszahl an, dass etwas Speicherplatz mit einem vollständigen Neupacken (dh einem git repack -a) zurückgewonnen werden könnte, wodurch die Wiederverwendung immer auf Null zurückgesetzt wird. Im Allgemeinen kümmert sich Git jedoch stillschweigend um all das für Sie. Außerdem kann das Ausführen vollständiger Neupakete dazu führen, dass einige Git-Abrufe von Grund auf neu gestartet werden, da sich die Pakete unterscheiden – dies hängt von den Servereinstellungen ab (das Zulassen der benutzerdefinierten Paketgenerierung pro Client ist teuer für die Server-CPU, daher deaktivieren einige große GIT-Sites dies).

Hoffentlich beantwortet dies Ihre Frage. Mit Git ist es wirklich so einfach, dass Sie anfangs erstaunt sind, dass es überhaupt funktioniert, und dann, wenn Sie sich damit beschäftigen, werden Sie ernsthaft beeindruckt. Nur wirklich geniale Programmierer können etwas so Einfaches schreiben, das aber so gut funktioniert, weil sie Einfachheit sehen können, wo die meisten Programmierer nur Komplexität sehen können.

Niall

  • Laut Manpage, git gc läuft git repack, also zu sagen, dass die beiden völlig unterschiedlich sind, scheint abwegig. Außerdem stammen die beiden ersten Beispiele (beide haben eine “wiederverwendete” Anzahl ungleich Null) aus einem Repository, das nur ein einziges Paket enthält, sodass Ihre Erklärung dort für mich keinen Sinn ergibt.

    – ich und

    27. Februar 2012 um 15:13 Uhr

  • Es gibt git repack und es gibt git repack – git gc, wenn ich mich erinnere, macht ein “leichtes” repack. In Bezug auf die wiederverwendete Anzahl stütze ich meine Antwort darauf, einen Fehler in Dulwich aufzuspüren, bei dem „extern zu diesem Paket“ Refs nicht zufrieden waren und Dulwich in eine Endlosschleife geriet. Ich gebe offen zu, dass ich den Git-Code nicht untersucht habe, um sicherzustellen, dass Wiederverwendung wirklich das bedeutet, was ich denke.

    – Niall Douglas

    28. Februar 2012 um 2:13 Uhr

  • In Bezug auf wiederverwendete Zählungen, die nicht auf Null gehen, versuchen Sie git repack -a, um ein vollständiges Neupacken zu erzwingen. Ich habe meine Antwort bearbeitet, um zu verdeutlichen, was ich mit “vollständig umpacken” gemeint habe. Versuchen Sie auch, das Fenster und die Tiefe während eines vollständigen Neupackens zu erhöhen (siehe linux.die.net/man/1/git-repack). Bei einem großen Repo können einige wiederverwendete Objekte, die aus dem Fenster gefallen sind, übrig bleiben.

    – Niall Douglas

    28. Februar 2012 um 2:23 Uhr

1217380cookie-checkWas bedeuten die Zahlen in der „Total“-Zeile der Ausgabe von git gc/git repack?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy