Skip to main content

Die vier fundamentalen Objekttypen in Git 🗃️

Git ist im Kern eine inhaltsadressierte Datenbank – jedes Objekt wird durch seinen SHA-1-Hash identifiziert. Diese Architektur basiert auf genau vier fundamentalen Objekttypen, die zusammen die gesamte Versionshistorie abbilden.


Die Objekttypen im Überblick

Blob – der Dateiinhalt 📄

Ein Blob (Binary Large Object) speichert den reinen Inhalt einer Datei – ohne Metadaten wie Dateinamen oder Berechtigungen. Zwei Dateien mit identischem Inhalt teilen sich denselben Blob, unabhängig von ihrem Namen oder Speicherort.

Eigenschaften:

  • Enthält ausschließlich den Dateiinhalt (Text oder Binärdaten)
  • Kennt seinen eigenen Dateinamen nicht
  • Wird durch den SHA-1-Hash seines Inhalts identifiziert

Tree – die Verzeichnisstruktur 🌳

Ein Tree repräsentiert ein Verzeichnis und verknüpft Dateinamen mit Blobs oder weiteren Trees (für Unterverzeichnisse). Er fungiert als „Inhaltsverzeichnis" eines Ordners zu einem bestimmten Zeitpunkt.

Jeder Eintrag in einem Tree enthält:

  • Den Dateimodus (z.B. 100644 fĂźr normale Dateien, 040000 fĂźr Verzeichnisse)
  • Den Objekttyp (blob oder tree)
  • Den SHA-1-Hash des referenzierten Objekts
  • Den Datei- oder Verzeichnisnamen

Commit – der Schnappschuss mit Geschichte 📸

Ein Commit ist der zentrale Objekttyp für die Versionskontrolle. Er referenziert einen Tree (den Zustand des gesamten Projekts) und enthält Metadaten zur Änderung.

Bestandteile eines Commits:

  • Referenz auf den Root-Tree (Projektzustand)
  • Referenz(en) auf Parent-Commit(s) – bei Merge-Commits mehrere
  • Autor (wer die Änderung ursprĂźnglich erstellt hat)
  • Committer (wer den Commit ins Repository eingefĂźgt hat)
  • Zeitstempel fĂźr beide
  • Die Commit-Nachricht

Tag – der benannte Meilenstein 🏷️

Ein annotiertes Tag ist ein eigenständiges Objekt, das auf einen Commit zeigt und zusätzliche Informationen enthält. Es dient typischerweise zur Markierung von Releases.

Bestandteile:

  • Referenz auf das getaggte Objekt (meist ein Commit)
  • Tag-Name
  • Tagger (Name und E-Mail)
  • Zeitstempel
  • Tag-Nachricht

💡 Hinweis: Sogenannte lightweight Tags sind keine eigenen Objekte, sondern nur Referenzen (wie Branches). Nur annotierte Tags (git tag -a) erzeugen ein Tag-Objekt.


Wie die Objekte zusammenhängen

Die Objekte bilden einen gerichteten azyklischen Graphen (DAG), in dem jedes Objekt auf andere verweist:

flowchart TB
    subgraph Commits
        C1["Commit abc123\nInitial commit"]
        C2["Commit def456\nAdd feature"]
    end
    
    subgraph Trees
        T1["Tree 1\nRoot-Verzeichnis"]
        T2["Tree 2\nRoot-Verzeichnis"]
        T3["Tree 3\nUnterordner src"]
    end
    
    subgraph Blobs
        B1["Blob\nREADME.md"]
        B2["Blob\nindex.js"]
        B3["Blob\napp.js"]
    end
    
    subgraph Tags
        TAG["Tag v1.0.0"]
    end
    
    TAG --> C2
    C2 --> C1
    C2 --> T2
    C1 --> T1
    
    T1 --> B1
    T2 --> B1
    T2 --> T3
    T3 --> B2
    T3 --> B3
    
    style TAG fill:#e1bee7,color:#000000
    style C1 fill:#bbdefb,color:#000000
    style C2 fill:#bbdefb,color:#000000
    style T1 fill:#c8e6c9,color:#000000
    style T2 fill:#c8e6c9,color:#000000
    style T3 fill:#c8e6c9,color:#000000
    style B1 fill:#fff9c4,color:#000000
    style B2 fill:#fff9c4,color:#000000
    style B3 fill:#fff9c4,color:#000000

Wichtige Zusammenhänge:

  • Ein Commit zeigt immer auf genau einen Tree (den Root-Tree)
  • Ein Tree zeigt auf Blobs (Dateien) und/oder andere Trees (Unterverzeichnisse)
  • Ein Commit zeigt auf seine Parent-Commits (außer der allererste)
  • Ein Tag zeigt typischerweise auf einen Commit

Objekte inspizieren mit git cat-file 🔍

Das Kommando git cat-file ist dein Werkzeug, um „unter die Haube" zu schauen. Es hat mehrere nützliche Optionen:

Option Beschreibung
-t Zeigt den Typ des Objekts
-s Zeigt die Größe in Bytes
-p Zeigt den Inhalt pretty-printed

Praktische Beispiele

  1. Typ eines Objekts ermitteln:

    git cat-file -t HEAD
    

    Ausgabe:

    commit
    
  2. Einen Commit inspizieren:

    git cat-file -p HEAD
    

    Ausgabe:

    tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
    parent 8a7b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
    author Max Mustermann <max@example.de> 1719670258 +0200
    committer Max Mustermann <max@example.de> 1719670258 +0200
    
    Implement user authentication
    
  3. Den Tree eines Commits anschauen:

    Zunächst den Tree-Hash aus dem Commit extrahieren, dann:

    git cat-file -p 4b825dc642cb6eb9a060e54bf8d69288fbee4904
    

    Ausgabe:

    100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    README.md
    100644 blob a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0    package.json
    040000 tree 9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e    src
    
  4. Einen Blob (Dateiinhalt) lesen:

    git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
    

    Ausgabe:

    # Mein Projekt
    
    Dies ist die README-Datei des Projekts.
    
  5. Ein annotiertes Tag inspizieren:

    git cat-file -p v1.0.0
    

    Ausgabe:

    object 8a7b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
    type commit
    tag v1.0.0
    tagger Max Mustermann <max@example.de> 1719670258 +0200
    
    Release version 1.0.0 - Production ready
    

NĂźtzliche AbkĂźrzungen

Du musst nicht immer den vollständigen SHA-1-Hash angeben:

# Die ersten 7 Zeichen reichen meist
git cat-file -p abc1234

# HEAD und andere Referenzen funktionieren
git cat-file -p HEAD
git cat-file -p main
git cat-file -p v1.0.0

# Der Tree des aktuellen Commits
git cat-file -p HEAD^{tree}

# Eine bestimmte Datei im aktuellen Commit
git cat-file -p HEAD:src/index.js

Wo liegen diese Objekte? 📂

Alle Objekte werden im Verzeichnis .git/objects/ gespeichert. Die ersten zwei Zeichen des Hashes bilden einen Unterordner, der Rest ist der Dateiname:

.git/objects/
├── 3b/
│   └── 18e512dba79e4c8300dd08aeb37f8e728b8dad   ← Blob
├── 4b/
│   └── 825dc642cb6eb9a060e54bf8d69288fbee4904   ← Tree
├── 8a/
│   └── 7b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b   ← Commit
└── pack/
    └── ...   ← Komprimierte Objekte (nach git gc)

Die Dateien sind mit zlib komprimiert – deshalb kannst du sie nicht direkt lesen, sondern brauchst git cat-file.

🎯 Tipp: Mit git count-objects -v siehst du, wie viele Objekte dein Repository enthält und wie viel Speicherplatz sie belegen.