Da Anonimo (non verificato) , 29 Aprile 2026

Introduzione

Il modello content-addressed di Git deduplica oggetti identici, ma blob simili-ma-non-identici (un file e la sua modifica successiva) costerebbero comunque dimensione piena ciascuno. I pack file risolvono questo con la compressione delta: memorizza un oggetto come una base più una sequenza di istruzioni "copy/insert" che producono un altro oggetto.

Come funziona

Quando impacchetta, Git confronta oggetti candidati (tipicamente blob di dimensione e tipo simili) e sceglie una base per ognuno. Il delta registra:

  • L'oggetto base (per offset all'interno del pack o per SHA).
  • Dimensioni di base e target.
  • Uno stream di istruzioni copy (usa byte dalla base) e insert (byte letterali).

Lo stream delta viene poi compresso con zlib.

Ispezionare i delta

git verify-pack -v .git/objects/pack/pack-<hash>.idx | head -20

Le colonne di output includono dimensione packed, profondità e SHA della base per le entry delta. Un oggetto non-delta non ha base.

Tunable

git config pack.window 250          # candidati esaminati per oggetto
git config pack.depth 50            # lunghezza massima della catena
git config pack.threads 4
git config pack.windowMemory 100m
git config pack.deltaCacheSize 256m

pack.window controlla quanto aggressivamente Git cerca buone basi; pack.depth limita quanto possono crescere le catene di delta.

Repack aggressivo vs normale

git repack -a -d                    # standard
git repack -a -d --depth=250 --window=250   # aggressivo
git gc --aggressive

I repack aggressivi gettano via i delta esistenti e ricalcolano da zero, costando CPU ma possibilmente migliorando il risultato.

Raggiungibilità e bitmap

I server spesso combinano packing delta con bitmap di raggiungibilità per il calcolo veloce del clone-set:

git repack -adb

Perché alcuni oggetti non sono deltificati

  • Dati casuali crittograficamente (già non comprimibili).
  • Oggetti i cui unici candidati sono più piccoli della soglia configurata.
  • Oggetti oltre la portata della pack window.

Delta cross-pack

Gli indici multi-pack (git multi-pack-index) più la modalità repack --geometric (Git 2.33+) rendono possibile mantenere delta tra molti pack efficientemente:

git repack --geometric=2 -d

Questo è lo schema raccomandato per repository grandi.

Delta islands

Per gli operatori di server che ospitano molti fork dello stesso progetto, i delta islands partizionano gli oggetti così i delta avvengono solo all'interno del set di ref di un fork, permettendo clone veloce di ogni singolo fork:

git config pack.island "refs/remotes/(.*)/heads"
git config pack.islandCore "main"
git repack -adb

Senza islands, un oggetto raggiungibile solo dal fork A potrebbe essere deltificato contro un oggetto raggiungibile solo dal fork B; servire il clone del fork A richiederebbe poi anche di inviare oggetti da B. La maggior parte degli utenti non ne ha mai bisogno, ma è la salsa segreta dietro la performance del pack server di GitHub, GitLab e Bitbucket.

Errori comuni

Assumere che i delta siano forward (più nuovo = base) o backward (più vecchio = base); Git è agnostico e sceglie quello che produce il delta più piccolo. Copiare pack tra repo con prefissi SHA diversi; i dati sono content-addressed quindi va bene, ma rinominare i file basandosi su hash parziali può rompere. Impostare pack.depth assurdamente alto in cerca di pack piccoli; catene più profonde significano accesso agli oggetti più lento (ogni delta nella catena deve essere applicato). Infine, aspettarsi che la compressione delta risparmi spazio su binari già compressi (video, JPG); non lo fa quasi mai. Usa Git LFS per quelli.