Einführung
Git speichert Objekte in zwei Formaten: lose (eine Datei pro Objekt unter .git/objects/xx/yyyy...) und gepackt (viele Objekte in einer einzigen .pack-Datei mit begleitender .idx). Packs sind weit effizienter auf Festplatte und im Netz.
Layout
.git/objects/
00/ ... lose Objekte, benannt nach SHA minus erste zwei Zeichen
pack/
pack-<hash>.pack # die Daten
pack-<hash>.idx # Offset-Index
pack-<hash>.rev # Rückwärts-Index (Git 2.31+)
Warum Packs
- Eine Datei pro Objekt ist auf Dateisystemen mit Millionen von Dateien brutal.
- Packs wenden Delta-Kompression an: ähnliche Blobs als Basis plus Diff speichern.
- Packs verwenden zusätzlich zu Deltas zlib.
- Smart Fetch/Push übertragen Pack-Daten direkt.
Packen auslösen
git gc # Routine-Wartung
git gc --aggressive # intensivere Delta-Suche
git repack -a -d -f # ein Pack aus allen Objekten neu erstellen
git fetch # kann ebenfalls Packs erzeugen
Auto-gc feuert, wenn das Repository zu viele lose Objekte ansammelt; einstellbar über gc.auto.
Packs inspizieren
ls .git/objects/pack
git verify-pack -v .git/objects/pack/pack-<hash>.idx | head
git count-objects -v
verify-pack -v zeigt Typ, Größe, gepackte Größe jedes Objekts und ob es ein Delta gegen ein anderes Objekt ist.
Multi-Pack-Indexe
Für sehr große Repositories können mehrere Packs durch einen einzigen Index vereinigt werden:
git multi-pack-index write
git config core.multiPackIndex true
Erreichbarkeits-Bitmaps
Bitmaps beschleunigen Erreichbarkeitsabfragen (von clone und fetch auf Hosting-Servern verwendet):
git repack -adb # Bitmap erstellen
git config repack.writeBitmaps true
Bitmaps sind am nützlichsten beim Bedienen vieler Klone oder beim Ausführen großer git rev-list-Abfragen.
Details der Objektkomprimierung
Ein Delta in einem Pack speichert eine Basis-Objektreferenz und einen Anweisungsstrom. Die Basis kann selbst ein Delta sein. Git begrenzt Delta-Ketten über pack.depth (Standard 50). Die gewählte Basis ist üblicherweise ein ähnlicher Blob, oft eine vorherige Version derselben Datei.
Geometrisches Repacking
Ein einziges riesiges Pack zu pflegen ist teuer; es bei jedem gc neu zu schreiben ist verschwenderisch. Modernes Git unterstützt geometrisches Repacking, das eine Kette von Packs geometrisch ansteigender Größe pflegt und nur die kleinen umpackt:
git repack --geometric=2 -d --write-bitmap-index
git config maintenance.incremental-repack.enabled true
git maintenance run --task incremental-repack
Dies macht die Routine-Wartung beschränkt: Jedes gc berührt nur die kleinsten Packs. Kombiniert mit Multi-Pack-Indexen und Erreichbarkeits-Bitmaps ist geometrisches Repack das empfohlene Setup für große oder beschäftigte Repositories.
Häufige Fehler
Manuelles Löschen einer .pack-Datei zur Speicherrückgewinnung, was das Repository bricht. Das Pack enthält viele erreichbare Objekte; verwenden Sie stattdessen git gc --prune. git gc --aggressive regelmäßig laufen lassen; es ist teuer und verbessert sich gegenüber einem normalen gc selten. Millionen lose Objekte behalten (nach einer verpfuschten Wiederherstellung) und dann git status auf einem langsamen Dateisystem ausführen; packen Sie zuerst. Schließlich: Packs durch Dateikopien statt durch git clone --bare übertragen; Sie verpassen möglicherweise die .idx oder überspringen neuere Funktionen wie den Multi-Pack-Index.