Einführung
"Erreichbarkeit" ist die wichtigste Eigenschaft eines Git-Objekts. Ein Objekt ist erreichbar, wenn eine Ref über Eltern- oder Tree-Verknüpfungen zu ihm führt. Unerreichbare Objekte kommen für Garbage Collection in Frage.
Erreichbarkeitsregeln
Ausgehend von irgendeiner Ref:
- Ein Commit erreicht seinen Wurzel-Tree, alle Eltern und (transitiv) deren Trees und Eltern.
- Ein Tree erreicht alle Einträge (Blobs und Subtrees).
- Ein Annotated Tag erreicht das getaggte Objekt.
Zu Refs gehören lokale Branches, Remote-Tracking-Branches, Tags, Stash, Notes und das Reflog (bis zum Ablauf).
Erreichbare Objekte auflisten
git rev-list --objects --all | head
git rev-list --objects HEAD
git rev-list --count HEAD
Vorfahrentests
git merge-base --is-ancestor X Y && echo "X is ancestor of Y"
git rev-list X..Y --count # wie viele Commits dazwischen liegen
git log --ancestry-path A..B --oneline # nur Commits auf dem Pfad A nach B
--ancestry-path ist unschätzbar, um die Kette von Commits zu finden, die einen Fix von einem Tag zum anderen brachte.
Bereichsoperatoren
A..B: erreichbar von B, nicht von A.A...B: symmetrische Differenz (eine Seite, nicht beide).^A B C: erreichbar von B oder C, aber nicht von A.
git log main..feature # durch feature hinzugefügte Commits
git log main...feature --left-right # beide Seiten markiert
Unerreichbare Objekte
git fsck --unreachable
git fsck --dangling
git fsck --lost-found # schreibt sie nach .git/lost-found
Unerreichbare Objekte überleben, bis git gc --prune sie entfernt; die Standard-Gnadenfrist beträgt zwei Wochen (gc.pruneExpire).
Die Rolle der commit-graph-Datei
Erreichbarkeits- und Vorfahrenabfragen sind der Engpass vieler Git-Operationen. Die commit-graph-Datei berechnet Generationsnummern und Elternlisten vor und macht diese Abfragen O(log n) statt O(n):
git commit-graph write --reachable
git config --global core.commitGraph true
Bitmap-Erreichbarkeit
Auf der Server-Seite erlauben Erreichbarkeits-Bitmaps Git, in Mikrosekunden zu beantworten, "welche Objekte sind von diesem Commit aus erreichbar?", indem ein vorberechnetes Bit pro Objekt gespeichert wird. Sie werden geschrieben durch:
git repack -adb
Durch Datum oder Pfad eingeschränkte Läufe
Die Erreichbarkeitsmaschinerie akzeptiert viele Beschränker, die mit der Bereichssyntax kombiniert werden:
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
Kombinieren Sie diese, um spezifische Fragen wie "Wie viele Nicht-Merge-Commits hat Ada im letzten Quartal auf main gelandet?" zu beantworten, ohne auf Shell-Pipelines zurückzugreifen. Die stabile Ausgabe von Plumbing macht das Ergebnis trivial in Reporting-Tools einspeisbar.
Häufige Fehler
Glauben, dass das Löschen eines Branches dessen Commits auslöscht; sie bleiben über das Reflog 90 Tage erreichbar und unerreichbar, aber nicht prunede für zwei weitere Wochen. A..B mit A...B verwechseln; eines ist asymmetrisch, das andere symmetrisch. HEAD~3 verwenden, um über Merges hinweg zu navigieren, und durch First-Parent-Traversierung verwirrt sein; verwenden Sie HEAD^2, um zum zweiten Elternteil zu wechseln. Schließlich: Erwarten, dass git fsck verlorene Commits nach einem frischen Klon findet; das Reflog und Dangling-Objekte existieren nur lokal dort, wo die Arbeit verrichtet wurde.