Einführung
Objekte sind unveränderlich und durch Hash benannt. Referenzen sind die veränderlichen, menschenlesbaren Namen, die auf sie zeigen. Jeder Branch, Tag, Remote-Tracking-Branch und HEAD ist eine Ref.
Wo Refs leben
Refs sind Dateien (oder Einträge in der packed-refs-Datei) unter .git/refs/:
.git/refs/heads/<name>: lokale Branches..git/refs/tags/<name>: Tags..git/refs/remotes/<remote>/<name>: Remote-Tracking-Branches..git/HEAD: die aktuelle Ref.
Jede nicht-symbolische Ref ist eine einzeilige Datei mit einem Hash:
cat .git/refs/heads/main
# a1b2c3d4...
Refs auflisten
git for-each-ref
git for-each-ref refs/tags/
git for-each-ref --format='%(refname:short) %(objectname:short) %(subject)'
git show-ref
Symbolische Refs
Eine symbolische Ref zeigt auf eine andere Ref statt auf einen Hash. HEAD ist das kanonische Beispiel:
cat .git/HEAD
# ref: refs/heads/main
git symbolic-ref HEAD
git symbolic-ref refs/remotes/origin/HEAD
Refs sicher lesen
Verwenden Sie immer Plumbing, anstatt Dateien zu lesen:
git rev-parse HEAD
git rev-parse main
git rev-parse origin/main
git rev-parse v1.0.0^{commit}
Plumbing handhabt packed Refs, symbolische Refs und Ref-Lookups einheitlich.
Refs aktualisieren
git update-ref refs/heads/feature/login <sha>
git update-ref -d refs/heads/feature/login # löschen
git update-ref refs/heads/feature/login <new> <old> # CAS
Die Drei-Argumente-Form ist Compare-and-Set; sie verweigert, wenn der aktuelle Wert abweicht.
Packed Refs
Aus Performance-Gründen kann Git viele Refs in eine einzige .git/packed-refs-Datei packen. git pack-refs --all tut dies; künftige Schreibvorgänge gehen weiterhin in lose Dateien, bis zum nächsten Pack.
Refspec-Syntax
Remotes verwenden Refspecs, um zwischen lokalen und Remote-Refs abzubilden:
+refs/heads/*:refs/remotes/origin/*
Das führende + bedeutet "Force Update". Diese eine Zeile ist es, was git fetch dazu bringt, refs/remotes/origin/ zu befüllen.
Das Reftable-Backend
Modernes Git (2.45+) liefert ein alternatives Ref-Speicherformat namens Reftable, ursprünglich für JGit entwickelt. Reftable speichert Millionen Refs effizient in einem binären log-strukturierten Format und unterstützt atomare Transaktionen über viele Refs hinweg. Aktivieren auf einem neuen Repository:
git init --ref-format=reftable
git rev-parse --show-ref-format
Für die meisten Nutzer ist das klassische lose+packed-Format weiterhin in Ordnung. Reftable glänzt auf Servern und auf riesigen Monorepos mit Hunderttausenden Refs (z. B. eine Ref pro Pull Request).
Eigene Ref-Hierarchien
Refs müssen nicht unter den vier Standard-Namespaces leben. Tools, die eigene Namen brauchen, verwenden eigene Hierarchien unter refs/:
refs/notes/*:git notes.refs/stash:git stash.refs/replace/*:git replace.refs/bisect/*:git bisect-Status.refs/pull/*/headundrefs/merge-requests/*/head: Hosting-Anbieter.
git for-each-ref refs/notes/
git for-each-ref refs/replace/
Sie können eigene erstellen, solange der Name eine gültige Ref ist (keine doppelten Punkte, keine Leerzeichen, kein führender Bindestrich).
Häufige Fehler
Ref-Dateien manuell editieren und mit einem Trailing-Newline-Problem oder einer halb geschriebenen Datei enden. Verwenden Sie git update-ref. refs/heads/main, main und refs/main verwechseln; git rev-parse --symbolic-full-name löst jeden Kurznamen zu seiner kanonischen Form auf. Einen Branch und einen Tag identisch benennen; Tools bevorzugen dann den Tag, was zu subtiler Verwirrung führt. Schließlich: .git/packed-refs löschen, um "aufzuräumen"; das löscht Refs, die nicht auch lose sind. Gehen Sie immer über Git.