Introduction
L'« atteignabilité » est la propriété la plus importante d'un objet Git. Un objet est atteignable si une ref y mène via les liens parent ou tree. Les objets inatteignables sont éligibles au garbage collection.
Règles d'atteignabilité
En partant de n'importe quelle ref :
- Un commit atteint son tree racine, tous les parents, et (transitivement) leurs trees et parents.
- Un tree atteint toutes les entrées (blobs et sous-trees).
- Un tag annoté atteint l'objet taggé.
Les refs incluent les branches locales, les branches de tracking distant, les tags, le stash, les notes et le reflog (jusqu'à expiration).
Lister les objets atteignables
git rev-list --objects --all | head
git rev-list --objects HEAD
git rev-list --count HEAD
Tests d'ancêtralité
git merge-base --is-ancestor X Y && echo "X est ancêtre de Y"
git rev-list X..Y --count # combien de commits entre
git log --ancestry-path A..B --oneline # uniquement commits sur le chemin A à B
--ancestry-path est précieux pour trouver la chaîne de commits qui a apporté un correctif d'un tag à un autre.
Opérateurs de plage
A..B: atteignable depuis B, pas depuis A.A...B: différence symétrique (l'un ou l'autre, pas les deux).^A B C: atteignable depuis B ou C mais pas A.
git log main..feature # commits ajoutés par feature
git log main...feature --left-right # les deux côtés étiquetés
Objets inatteignables
git fsck --unreachable
git fsck --dangling
git fsck --lost-found # les écrit dans .git/lost-found
Les objets inatteignables survivent jusqu'à ce que git gc --prune les supprime ; la période de grâce par défaut est deux semaines (gc.pruneExpire).
Le rôle du fichier commit-graph
Les requêtes d'atteignabilité et d'ancêtralité sont le goulot d'étranglement de nombreuses opérations Git. Le fichier commit-graph précalcule les numéros de génération et les listes de parents, rendant ces requêtes O(log n) au lieu de O(n) :
git commit-graph write --reachable
git config --global core.commitGraph true
Atteignabilité par bitmap
Côté serveur, les bitmaps d'atteignabilité permettent à Git de répondre à « quels objets sont atteignables depuis ce commit ? » en microsecondes, en stockant un bit précalculé par objet. Ils sont écrits par :
git repack -adb
Parcours limités par date ou chemin
La machinerie d'atteignabilité accepte de nombreux limiteurs qui se combinent avec la syntaxe de plage :
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
Combinez-les pour répondre à des questions spécifiques comme « combien de commits non-merge Ada a-t-elle déposés sur main au dernier trimestre ? » sans recourir à des pipelines shell. La sortie stable de la plomberie rend le résultat trivial à introduire dans des outils de reporting.
Erreurs fréquentes
Croire qu'une branche supprimée efface ses commits ; ils restent atteignables via le reflog pendant 90 jours, et inatteignables mais non élagués pendant deux semaines de plus. Confondre A..B avec A...B ; l'un est asymétrique, l'autre symétrique. Utiliser HEAD~3 pour naviguer à travers les merges et être perplexe par la traversée du premier parent ; utilisez HEAD^2 pour passer au second parent. Enfin, attendre que git fsck trouve des commits perdus après un clone frais ; le reflog et les objets pendants n'existent que localement où le travail a été fait.