Introduzione
Git memorizza gli oggetti in due formati fisici. Gli oggetti loose sono file individuali; gli oggetti packed vivono dentro un pack file con un corpo compresso a delta. Entrambe le forme descrivono gli stessi oggetti logici, indirizzati dagli stessi hash.
Layout loose
Ogni oggetto loose è in .git/objects/xx/yyy..., dove xx sono i primi due caratteri esadecimali dello SHA e yyy... sono i restanti 38. Il file è il byte deflato con zlib di <type> <size>\0<content>:
find .git/objects -type f -name '??' -prune -o -type f -print | head
git cat-file -p <sha>
Layout pack
.git/objects/pack/pack-<hash>.pack
.git/objects/pack/pack-<hash>.idx
Il file .idx mappa SHA a offset di byte all'interno del .pack; senza di esso, il pack richiederebbe una scansione lineare.
Come gli oggetti si muovono tra forme
I nuovi oggetti vengono scritti loose. Diventano packed quando:
git gcviene eseguito (manuale o automatico).git repackviene invocato.- Un fetch o push li trasferisce come pack.
git fast-importli scrive direttamente in un pack.
git gc
git repack -a -d
git count-objects -v
count-objects -v riporta conteggio loose, uso totale del disco e statistiche dei pack.
Compromessi
- Loose: semplice, facile da ispezionare, veloce per scrivere un singolo oggetto. Lento quando ce ne sono milioni.
- Packed: compatto, compresso a delta, veloce per letture in massa. Richiede repacking per incorporare nuovi oggetti.
Auto-gc
Git innesca un auto-gc quando troppi oggetti loose si accumulano. Tunable:
git config gc.auto 6700 # soglia per oggetti loose
git config gc.autoPackLimit 50 # soglia per numero di pack
git config gc.auto 0 # disabilita auto-gc (sconsigliato)
Ispezionare un pack
git verify-pack -v .git/objects/pack/pack-<hash>.idx | head
git verify-pack -s .git/objects/pack/pack-<hash>.idx
Vedrai tipi di oggetto, dimensioni packed, delta e profondità della catena.
Recuperare da corruzione
git fsck --full
cp -r broken-repo backup
git unpack-objects < .git/objects/pack/pack-<hash>.pack
unpack-objects esplode un pack di nuovo in forma loose, utile quando un singolo oggetto cattivo dentro un pack sta abbattendo molte operazioni.
Cercare un oggetto
Quando Git risolve uno SHA, cerca in questo ordine: file oggetto loose, poi ogni idx di pack, poi alternates (objects/info/alternates). Il lookup è essenzialmente a tempo costante per pack grazie alla tabella fanout dell'idx. L'impatto sulla performance di avere molti pack piccoli vs un pack grande è reale, ed è per questo che gc consolida:
git count-objects -v
cat .git/objects/info/alternates 2>/dev/null
git verify-pack -s .git/objects/pack/pack-<hash>.idx
Gli alternates permettono a più repo di condividere un pool di oggetti su disco; git clone --shared crea tale setup e risparmia spazio al costo di un po' di sicurezza.
Errori comuni
Cancellare manualmente file pack- per recuperare spazio; questo distrugge la storia raggiungibile. Usa git gc. Disabilitare auto-gc su repo di lunga vita e finire con milioni di oggetti loose, rallentando ogni operazione. Eseguire git gc --aggressive regolarmente quando un gc normale basterebbe; il packing aggressivo è costoso. Infine, copiare un repo con cp -r mentre un pack è in scrittura, finendo con un index corrotto. Usa git clone --local per copie sicure.