Introduzione
Git memorizza gli oggetti in due formati: loose (un file per oggetto sotto .git/objects/xx/yyyy...) e packed (molti oggetti in un singolo file .pack con un compagno .idx). I pack sono molto più efficienti su disco e in rete.
Layout
.git/objects/
00/ ... oggetti loose, nominati per sha meno i primi due caratteri
pack/
pack-<hash>.pack # i dati
pack-<hash>.idx # indice di offset
pack-<hash>.rev # indice inverso (Git 2.31+)
Perché i pack
- Un file per oggetto è brutale sui filesystem con milioni di file.
- I pack applicano compressione delta: memorizzano blob simili come una base più un diff.
- I pack usano zlib oltre ai delta.
- Smart fetch/push trasferiscono i dati pack direttamente.
Innescare il packing
git gc # manutenzione di routine
git gc --aggressive # ricerca delta più pesante
git repack -a -d -f # ricrea un pack da tutti gli oggetti
git fetch # può anche produrre pack
L'auto-gc scatta quando il repo accumula troppi oggetti loose; regola con gc.auto.
Ispezionare i pack
ls .git/objects/pack
git verify-pack -v .git/objects/pack/pack-<hash>.idx | head
git count-objects -v
verify-pack -v mostra il tipo, dimensione, dimensione packed di ogni oggetto e se è un delta contro un altro oggetto.
Indici multi-pack
Per repo molto grandi, più pack possono essere unificati da un singolo indice:
git multi-pack-index write
git config core.multiPackIndex true
Bitmap di raggiungibilità
I bitmap accelerano le query di raggiungibilità (usate da clone e fetch sui server di hosting):
git repack -adb # costruisce il bitmap
git config repack.writeBitmaps true
I bitmap sono più utili quando si servono molti clone o quando si eseguono grandi query git rev-list.
Dettagli di compressione degli oggetti
Un delta in un pack memorizza un riferimento a un oggetto base e uno stream di istruzioni. La base può essa stessa essere un delta. Git limita le catene di delta tramite pack.depth (default 50). La base scelta è di solito un blob simile, spesso una versione precedente dello stesso file.
Repack geometrico
Mantenere un singolo pack enorme è costoso; riscriverlo a ogni gc è dispendioso. Git moderno supporta il repack geometrico, che mantiene una catena di pack di dimensione geometricamente crescente e fa repack solo dei piccoli:
git repack --geometric=2 -d --write-bitmap-index
git config maintenance.incremental-repack.enabled true
git maintenance run --task incremental-repack
Questo rende la manutenzione di routine limitata: ogni gc tocca solo i pack più piccoli. Combinato con indici multi-pack e bitmap di raggiungibilità, il repack geometrico è la configurazione consigliata per repository grandi o trafficati.
Errori comuni
Cancellare manualmente un file .pack per recuperare spazio, rompendo il repo. Il pack contiene molti oggetti raggiungibili; usa invece git gc --prune. Eseguire git gc --aggressive programmato; è costoso e raramente migliora rispetto a un normale gc. Tenere milioni di oggetti loose (dopo un recupero pasticciato) e poi fare git status su un filesystem lento; impacchetta prima. Infine, trasferire pack copiando i file invece di usare git clone --bare; potresti perdere il .idx o saltare funzionalità più nuove come l'indice multi-pack.