Introduzione
La "raggiungibilità" è la proprietà più importante di un oggetto Git. Un oggetto è raggiungibile se qualche ref porta ad esso tramite link parent o tree. Gli oggetti irraggiungibili sono candidabili al garbage collection.
Regole di raggiungibilità
Partendo da un ref qualsiasi:
- Un commit raggiunge il suo tree radice, tutti i parent, e (transitivamente) i tree e parent di quei parent.
- Un tree raggiunge tutte le entry (blob e sotto-tree).
- Un tag annotated raggiunge l'oggetto taggato.
I ref includono branch locali, branch di tracking remoto, tag, stash, notes e il reflog (fino alla scadenza).
Elencare oggetti raggiungibili
git rev-list --objects --all | head
git rev-list --objects HEAD
git rev-list --count HEAD
Test di antenato
git merge-base --is-ancestor X Y && echo "X è antenato di Y"
git rev-list X..Y --count # quanti commit ci sono in mezzo
git log --ancestry-path A..B --oneline # solo commit sul percorso da A a B
--ancestry-path è prezioso per trovare la catena di commit che ha portato un fix da un tag a un altro.
Operatori di range
A..B: raggiungibile da B, non da A.A...B: differenza simmetrica (uno dei due, non entrambi).^A B C: raggiungibile da B o C ma non da A.
git log main..feature # commit aggiunti da feature
git log main...feature --left-right # entrambi i lati etichettati
Oggetti irraggiungibili
git fsck --unreachable
git fsck --dangling
git fsck --lost-found # li scrive in .git/lost-found
Gli oggetti irraggiungibili sopravvivono finché git gc --prune non li rimuove; il periodo di grazia predefinito è due settimane (gc.pruneExpire).
Il ruolo del file commit-graph
Le query di raggiungibilità e antenato sono il collo di bottiglia di molte operazioni Git. Il file commit-graph precalcola i numeri di generazione e le liste di parent, rendendo queste query O(log n) invece di O(n):
git commit-graph write --reachable
git config --global core.commitGraph true
Bitmap di raggiungibilità
Lato server, i bitmap di raggiungibilità permettono a Git di rispondere a "quali oggetti sono raggiungibili da questo commit?" in microsecondi, memorizzando un bit precalcolato per oggetto. Vengono scritti da:
git repack -adb
Walk limitati per data o path
Il macchinario di raggiungibilità accetta molti limitatori che si combinano con la sintassi di range:
git rev-list --since=2024-01-01 main
git rev-list main -- path/to/file
git rev-list --no-merges main..feature
git rev-list --first-parent main
git rev-list HEAD --count
Combinali per rispondere a domande specifiche come "quanti commit non-merge ha rilasciato Ada su main lo scorso trimestre?" senza ricorrere a pipeline di shell. L'output stabile del plumbing rende il risultato banale da alimentare in strumenti di reportistica.
Errori comuni
Credere che un branch cancellato cancelli i suoi commit; rimangono raggiungibili attraverso il reflog per 90 giorni, e irraggiungibili ma non potati per altre due settimane. Confondere A..B con A...B; uno è asimmetrico, l'altro simmetrico. Usare HEAD~3 per navigare attraverso i merge ed essere confusi dalla traversata first-parent; usa HEAD^2 per passare al secondo parent. Infine, aspettarsi che git fsck trovi commit persi dopo un clone fresco; il reflog e gli oggetti dangling esistono solo localmente dove è stato fatto il lavoro.