Von Gast (nicht überprüft) , 29 April 2026

Einführung

Gits Repository ist im Kern ein inhaltsadressierter Objektspeicher. Es gibt genau vier Objekttypen: Blob, Tree, Commit und Tag. Jede Operation berührt sie letztlich. Diese vier Typen zu verstehen entmystifiziert das meiste an Git.

Blobs

Ein Blob speichert Dateiinhalte, mehr nicht. Kein Dateiname, keine Berechtigungen, keine Historie. Zwei Dateien mit identischem Inhalt teilen sich einen Blob, unabhängig davon, wo sie im Tree liegen.

echo "hello" | git hash-object --stdin
# ce013625030ba8dba906f756967f9e9ca394464a

Trees

Ein Tree ist ein Verzeichniseintrag: eine sortierte Menge von (mode, type, sha, name)-Einträgen. Unterverzeichnisse sind selbst Trees, rekursiv. Jeder Commit zeigt auf genau einen Wurzel-Tree.

git ls-tree HEAD
# 100644 blob a1b2... README.md
# 040000 tree c3d4... src

Commits

Ein Commit-Objekt enthält:

  • Einen Zeiger auf einen Wurzel-Tree.
  • Null oder mehr Eltern-Commits (null für die Wurzel, zwei oder mehr für Merges).
  • Autor und Committer mit Zeitstempeln.
  • Eine Nachricht.
  • Optionale GPG/SSH-Signatur.
git cat-file -p HEAD
# tree 9f1a...
# parent b2c3...
# author Ada <[email protected]> 1714300000 +0000
# committer Ada <[email protected]> 1714300000 +0000
#
# Add greeting

Tags

Ein annotated Tag ist ein eigenes Objekt, das auf ein anderes Objekt zeigt (fast immer einen Commit), mit Tagger-Info und einer Nachricht. Lightweight-Tags sind nur Refs und haben kein Objekt.

git cat-file -t v1.0.0
# tag
git cat-file -p v1.0.0

Zusammensetzen

Den Tree eines Commits manuell durchlaufen:

git cat-file -p HEAD^{tree}
git cat-file -p HEAD^{tree}:src
git cat-file -p HEAD:README.md

Die ^{tree}-Peel- und die commit:path-Syntax sind die Art, wie alle Git-Werkzeuge navigieren.

Speicherung

Jedes Objekt ist zlib-komprimiert und adressiert durch den SHA-1 (oder SHA-256) seines unkomprimierten Inhalts plus Header. Identischer Inhalt, irgendwo in der Historie, dedupliziert sich automatisch.

Tree-Eintragsmodi

Das mode-Feld in einem Tree-Eintrag ist eine kleine Menge POSIX-ähnlicher Dateimodi:

  • 100644: reguläre nicht-ausführbare Datei (Blob).
  • 100755: ausführbare Datei (Blob).
  • 120000: symbolischer Link (Blob, dessen Inhalt das Ziel ist).
  • 040000: Unterverzeichnis (Tree).
  • 160000: Gitlink (Submodule-Referenz auf einen Commit-SHA).
git ls-tree HEAD
git update-index --chmod=+x scripts/run.sh
git ls-tree HEAD scripts/

Git ist absichtlich begrenzt; willkürliche Berechtigungen und Eigentümerschaften werden nicht gespeichert.

Häufige Fehler

Glauben, dass Git Diffs speichert. Tut es nicht; es speichert vollständige Snapshots, dedupliziert nach Hash und später Delta-komprimiert in Pack-Dateien. Trees mit Verzeichnissen auf der Festplatte verwechseln; Trees sind unveränderliche Objekte. Lightweight-Tags mit annotated verwechseln; nur annotated Tags tragen Metadaten und Signaturen. Schließlich: Erwarten, dass das Umbenennen einer Datei den Blob ändert; der Blob ist derselbe, nur der Name-Eintrag des Trees ändert sich. Verbringen Sie zehn Minuten mit git cat-file -p auf einem echten Repository und das Modell wird zur zweiten Natur.