Git-Grundlagen: Working Directory, Staging Area, Repository verstehen
git
HEAD
Git · Version Control · Fundamentals · Entwickler-Basics
Git-Grundlagen: Working Directory, Staging Area, Repository verstehen
Warum git add ein eigener Schritt ist

Wer Git nur als Blackbox mit mysteriösen Befehlen begreift, tippt Kommandos nach Gefühl und wundert sich über Fehlermeldungen. Dieser Artikel erklärt das Drei-Bereiche-Modell aus Working Directory, Staging Area und Repository, zeigt was git add, commit, checkout und restore technisch wirklich tun, und liefert damit das Mentalmodell, mit dem spätere Git-Konzepte wie Branches, Merges und Reset endlich logisch werden.

12 Min. Lesezeit Working Directory · Staging Area · Repository Git 2.x · CLI · Entwickleralltag

1. Warum die Drei-Bereiche-Architektur das Fundament von Git ist

Die meisten Verwirrungen von Git-Einsteigern lassen sich auf eine einzige Ursache zurückführen: Sie behandeln Git wie ein einfaches Backup-Tool mit einem einzigen Zustand pro Datei. In Wirklichkeit verwaltet Git jede Datei potenziell in drei unterschiedlichen Zuständen gleichzeitig: im Working Directory, in der Staging Area und im Repository. Diese Drei-Bereiche-Architektur ist kein Designzufall, sondern die zentrale Idee, die Git von älteren Versionskontrollsystemen wie SVN unterscheidet.

Wer dieses Modell einmal verinnerlicht hat, versteht auf einen Schlag, warum git add ein separater Schritt ist, warum git status drei verschiedene Kategorien von Änderungen anzeigt, und warum git reset in mehreren Varianten existiert. Ohne dieses Mentalmodell wirken Git-Befehle wie auswendig gelernte Zaubersprüche. Mit ihm werden sie zu logischen Operationen, die Daten gezielt zwischen drei klar definierten Bereichen bewegen. Genau dieses Modell baut dieser Artikel Schritt für Schritt auf.

2. Working Directory: der sichtbare Zustand deiner Dateien

Das Working Directory (Arbeitsverzeichnis) ist der Ordner auf der Festplatte, in dem tatsächlich mit Dateien gearbeitet wird. Es ist der einzige der drei Bereiche, den ein Texteditor oder eine IDE direkt sieht. Jede Änderung, die durch Tippen, Speichern oder das Ausführen eines Code-Generators entsteht, landet zunächst und ausschließlich hier. Git beobachtet dieses Verzeichnis, verändert es aber nicht von sich aus, solange keine expliziten Befehle wie checkout oder restore aufgerufen werden.

Wichtig ist: Das Working Directory kennt keine Git-Historie. Eine Datei dort ist entweder identisch mit der zuletzt committeten Version, unterscheidet sich davon (modifiziert), oder ist komplett neu und Git noch unbekannt (untracked). Diese drei Zustände, "unverändert", "modifiziert" und "untracked", bilden die Grundlage für alles, was git status später anzeigt. Ein häufiger Anfängerfehler ist die Annahme, eine gespeicherte Datei sei automatisch "in Git" - tatsächlich weiß Git von einer neuen Datei erst, wenn sie explizit mit git add erfasst wird.

3. Staging Area (Index): die Zwischenablage für den nächsten Commit

Die Staging Area, auch Index genannt, ist der eigentliche Unterschied zwischen Git und den meisten anderen Versionskontrollsystemen. Sie ist eine binäre Datei unter .git/index, die eine Momentaufnahme dessen enthält, was beim nächsten git commit tatsächlich gespeichert wird. Der entscheidende Punkt: Die Staging Area ist unabhängig vom Working Directory. Eine Datei kann im Arbeitsverzeichnis bereits weiterbearbeitet worden sein, während im Index noch eine ältere Zwischenversion liegt, die gestaged wurde.

Diese Entkopplung erlaubt gezieltes, selektives Committen. Statt alle Änderungen einer Arbeitssitzung in einen einzigen, unübersichtlichen Commit zu packen, kann man mit git add -p genau die Zeilen auswählen, die logisch zusammengehören, und einen sauberen, fokussierten Commit erzeugen. Der Index ist technisch eine flache Liste aus Dateipfad, Blob-Hash und Metadaten, vergleichbar mit einem Verzeichnisbaum, der aber vollständig getrennt von den echten Dateien im Working Directory existiert. Genau das macht ihn zu einer echten Zwischenablage statt einer bloßen Markierung.


# ~/.gitconfig: aliases that make the Staging Area explicit in daily work
[alias]
	# Show only what is currently staged (Index vs HEAD)
	staged = diff --staged

	# Unstage a file: copy HEAD back into the Index, keep Working Directory
	unstage = restore --staged

	# Interactive, hunk-by-hunk staging
	addp = add --patch

	# Status in compact form: two columns show Index vs HEAD and WD vs Index
	s = status --short --branch

4. Repository und HEAD: der Verlauf, der niemals lügt

Das Repository ist die Datenbank unter .git/objects, in der jeder Commit als unveränderlicher Snapshot gespeichert wird. Anders als Working Directory und Staging Area, die beide veränderlich und flüchtig sind, ist ein einmal erstellter Commit in seiner ursprünglichen Form für immer erhalten, solange kein Garbage Collection die verwaisten Objekte entfernt. Jeder Commit referenziert seinen Vorgänger über dessen Hash und bildet so eine gerichtete, azyklische Historie.

HEAD ist dabei kein Bereich für sich, sondern ein Zeiger, der normalerweise auf den aktuellen Branch zeigt, welcher wiederum auf den letzten Commit dieses Branches zeigt. Wenn Git-Dokumentation von "HEAD" spricht, meint sie meist "der zuletzt committete Zustand des aktuellen Branches" - also die Referenzversion, mit der Working Directory und Staging Area beim git status verglichen werden. Ein Commit-Objekt selbst besteht aus einem Verweis auf einen Baum (Tree), der wiederum den vollständigen Zustand aller Dateien zu diesem Zeitpunkt abbildet - nicht als Diff, sondern als kompletter, adressierbarer Snapshot.


# The three trees in action: create, stage, commit
$ echo "console.log('hello');" > app.js
$ git status
Untracked files:
  app.js

$ git add app.js
$ git status
Changes to be committed:
  new file:   app.js

$ git commit -m "Add app.js"
[main a1b2c3d] Add app.js
 1 file changed, 1 insertion(+)

# Now modify the working directory again, index stays untouched
$ echo "console.log('world');" >> app.js
$ git status
Changes not staged for commit:
  modified:   app.js

# Working Directory != Staging Area != Repository, all three differ now

5. git add im Detail: was wirklich beim Stagen passiert

git add tut technisch zwei Dinge: Es erstellt ein neues Blob-Objekt im Repository, das den aktuellen Inhalt der Datei als komprimierten, per SHA-1 oder SHA-256 adressierten Snapshot speichert, und es aktualisiert den Index-Eintrag für diesen Pfad auf den Hash dieses neuen Blobs. Wichtig: Der Blob landet bereits im Objektspeicher unter .git/objects, obwohl noch kein Commit existiert. Das erklärt, warum gestagte, aber nicht committete Änderungen mit git fsck --lost-found nach einem versehentlichen reset --hard oft noch wiederherstellbar sind.

Der entscheidende Grund, warum git add ein separater Schritt ist: Es entkoppelt die Frage "was habe ich verändert" von der Frage "was soll ein zusammenhängender Commit werden". Ohne Staging Area müsste jeder commit-Aufruf zwangsläufig alle Änderungen im Arbeitsverzeichnis erfassen - genau das Verhalten, das viele SVN-Nutzer aus Gewohnheit erwarten und das in Git bewusst vermieden wird. Mit git add -p app.js lässt sich sogar innerhalb einer einzelnen Datei zeilenweise entscheiden, welche Änderung in den nächsten Commit soll und welche für später im Working Directory bleibt.

Wer diesen Mechanismus mit git ls-files --stage nachvollzieht, sieht direkt, dass der Index nichts weiter als eine flache Liste aus Dateipfad, Modus und Blob-Hash ist: 100644 3b18e512d...b8dad 0 app.js. Mit git cat-file -p <hash> lässt sich der Inhalt dieses Blobs sogar auslesen, obwohl noch nie ein Commit stattgefunden hat. Das macht sichtbar, dass Staging kein reiner Merkzettel ist, sondern bereits echte Objekte im Repository anlegt.

6. git commit im Detail: Snapshots statt Diffs

Ein weit verbreitetes Missverständnis ist, Git speichere Commits als Diffs, ähnlich wie ältere Versionskontrollsysteme. Tatsächlich erstellt git commit einen vollständigen Tree-Snapshot des gesamten Index-Zustands. Für unveränderte Dateien werden dabei keine neuen Blobs erzeugt - Git erkennt anhand des bereits bekannten Hashes, dass der Inhalt identisch ist, und referenziert einfach das existierende Objekt. Das macht Commits speichereffizient, obwohl sie konzeptionell vollständige Snapshots sind, keine inkrementellen Deltas.

Ein Commit-Objekt besteht aus vier Bestandteilen: dem Hash des Root-Trees, dem Hash des Elterncommits (oder mehreren bei einem Merge), Autor- und Committer-Metadaten mit Zeitstempel, sowie der Commit-Message. Nach dem erfolgreichen Commit passiert etwas Entscheidendes: Der Branch-Zeiger, auf den HEAD zeigt, wird auf den Hash des neuen Commits aktualisiert. Working Directory und Staging Area sind nach einem Commit wieder identisch mit dem Repository-Zustand - bis zur nächsten Änderung im Arbeitsverzeichnis beginnt der Zyklus von vorn.


# .pre-commit-config.yaml: hooks that operate only on staged content
repos:
  - repo: https://github.com/pre-commit/mirrors-phpcs
    rev: v3.9.0
    hooks:
      - id: phpcs
        # Runs only against files currently in the Staging Area,
        # never against unstaged Working Directory changes
        files: \.php$
        args: ["--standard=PSR12"]

  - repo: local
    hooks:
      - id: no-debug-statements
        name: Block var_dump/dd() in staged PHP files
        entry: sh -c '! git diff --staged --name-only | grep "\.php$" | xargs grep -l "var_dump\|dd("'
        language: system
        stages: [commit]

7. git checkout, restore und reset: Dateien zwischen den Bereichen bewegen

Sobald das Drei-Bereiche-Modell verstanden ist, lassen sich checkout, restore und reset als gezielte Kopieroperationen zwischen den Bereichen begreifen, statt als unzusammenhängende Befehle. git checkout -- datei.txt (bzw. moderner git restore datei.txt) kopiert die Version aus dem Index zurück ins Working Directory und überschreibt dabei unwiderruflich lokale Änderungen. git restore --staged datei.txt geht den umgekehrten Weg: Es kopiert die Version aus dem letzten Commit (HEAD) zurück in den Index, ohne das Working Directory anzufassen - die Datei wird also "unstaged", bleibt aber im Arbeitsverzeichnis verändert.

git reset operiert auf HEAD und dem Branch-Zeiger selbst und hat drei Modi mit unterschiedlicher Reichweite: --soft bewegt nur HEAD, Index und Working Directory bleiben unverändert - die Änderungen des rückgängig gemachten Commits landen als bereits gestagte Änderungen im Index. --mixed (Standard) bewegt zusätzlich den Index auf den Zielzustand, das Working Directory bleibt unverändert. --hard überschreibt zusätzlich auch das Working Directory und ist damit der einzige der drei Modi, der unwiderruflich lokale Änderungen löschen kann.


# git restore: copy Index -> Working Directory (discards local edits)
$ git restore app.js
$ git diff app.js
# no output: Working Directory now matches the Index again

# git restore --staged: copy HEAD -> Index (unstage, keep local edits)
$ git restore --staged app.js
$ git status
Changes not staged for commit:
  modified:   app.js

# git reset moves HEAD and the branch pointer, with three levels of reach
$ git reset --soft HEAD~1   # only HEAD moves, Index and WD untouched
$ git reset --mixed HEAD~1  # HEAD + Index move, WD untouched (default)
$ git reset --hard HEAD~1   # HEAD + Index + WD all overwritten, irreversible

8. git status und git diff: die drei Bereiche sichtbar machen

git status ist im Kern nichts anderes als ein dreifacher Vergleich: Working Directory gegen Index, und Index gegen HEAD. Die Ausgabe "Changes to be committed" listet Unterschiede zwischen Index und HEAD auf - das, was beim nächsten Commit gespeichert würde. "Changes not staged for commit" listet Unterschiede zwischen Working Directory und Index auf - Änderungen, die zwar auf der Festplatte existieren, aber noch nicht für den nächsten Commit vorgemerkt sind. "Untracked files" sind Pfade, die in keinem der beiden anderen Bereiche vorkommen.

Dieselbe Logik gilt für git diff, ein Befehl, der Einsteiger regelmäßig verwirrt, weil er je nach Flag unterschiedliche Bereiche vergleicht. git diff ohne Parameter vergleicht Working Directory gegen Index - genau die Änderungen, die ein git add als nächstes erfassen würde. git diff --staged (Synonym: --cached) vergleicht Index gegen HEAD - genau die Änderungen, die ein git commit als nächstes speichern würde. Wer diese beiden Kommandos verwechselt, sieht scheinbar "keine Änderungen", obwohl tatsächlich gestagte Änderungen vorliegen, die einfach mit dem falschen Diff-Modus abgefragt wurden.


# git diff compares Working Directory vs Index
$ git diff
diff --git a/app.js b/app.js
-console.log('hello');
+console.log('hello world');

# git diff --staged compares Index vs HEAD (the last commit)
$ git add app.js
$ git diff --staged
diff --git a/app.js b/app.js
-console.log('hello');
+console.log('hello world');

# After the change above is also staged, plain "git diff" shows nothing
$ git diff
$ echo "No output: Working Directory now equals Index"

9. Das Drei-Bäume-Mentalmodell im direkten Vergleich

Die Git-Dokumentation selbst nennt Working Directory, Staging Area und HEAD gelegentlich die "drei Bäume" (three trees), weil jeder Bereich intern durch einen Tree-artigen Zustand repräsentiert wird, auch wenn nur der Repository-Teil tatsächlich als Tree-Objekt gespeichert ist. Für den Alltag reicht ein einfacheres Bild: Working Directory ist der Entwurf, Staging Area ist das, was gleich in den Umschlag kommt, und Repository ist der bereits abgeschickte, unveränderliche Brief. Jeder Git-Befehl bewegt Inhalte gezielt zwischen genau zwei dieser drei Stationen.

Die folgende Tabelle löst die häufigsten Missverständnisse von Einsteigern auf, indem sie den intuitiven, aber falschen Reflex dem tatsächlichen Verhalten von Git gegenüberstellt.

Situation Häufiges Missverständnis Korrektes Mentalmodell Warum das wichtig ist
git add datei.txt Datei ist jetzt gespeichert/committet Blob liegt nur im Index, Repository unverändert Verhindert falsche Sicherheit vor dem Commit
git commit ohne vorheriges add Alle Änderungen werden automatisch committet Nur was im Index steht wird committet Erklärt "nothing to commit, working tree clean"
git checkout -- datei.txt Harmlose, rein kosmetische Aktion Überschreibt Working Directory unwiderruflich Verhindert Verlust lokaler Änderungen
git reset HEAD~1 Löscht den letzten Commit vollständig Bewegt nur den Branch-Zeiger, Objekte bleiben erhalten Erklärt, warum reset meist reversibel ist
git diff ohne Parameter Zeigt alle offenen Änderungen Zeigt nur Working Directory vs. Index Erklärt die Rolle von --staged/--cached

Wer diese fünf Zeilen verinnerlicht hat, hat den größten Teil der typischen Git-Verwirrung bereits aufgelöst. Alle weiteren Befehle, von git stash bis git cherry-pick, lassen sich letztlich auf dieselbe Frage zurückführen: Welcher der drei Bereiche wird hier gelesen, und welcher wird geschrieben?

Mironsoft

Git-Workflows, Code-Reviews und CI/CD-Pipelines für PHP- und Magento-Teams

Saubere Git-Workflows im Team etablieren?

Wir helfen Entwicklerteams, Branching-Strategien, Commit-Konventionen und Review-Prozesse einzuführen, die auf einem soliden Verständnis von Working Directory, Staging Area und Repository aufbauen.

Git-Schulung

Praxisnahe Workshops zu Staging, Branching und Merge-Strategien für Teams

Workflow-Audit

Bestehende Git-Prozesse analysieren und auf saubere Commit-Historie trimmen

CI/CD-Integration

Pre-Commit-Hooks, Linting und automatisierte Pipelines rund um Git aufsetzen

10. Zusammenfassung

Das Drei-Bereiche-Modell von Git, Working Directory, Staging Area und Repository, ist kein Detail für Fortgeschrittene, sondern das Fundament, auf dem jeder weitere Git-Befehl aufbaut. Das Working Directory ist der sichtbare, veränderliche Zustand auf der Festplatte. Die Staging Area ist eine bewusst entkoppelte Zwischenablage, die selektives, fokussiertes Committen ermöglicht. Das Repository speichert Commits als unveränderliche, vollständige Snapshots, nicht als Diffs, und HEAD zeigt dabei stets auf den zuletzt committeten Zustand des aktuellen Branches.

git add kopiert vom Working Directory in den Index, git commit kopiert vom Index ins Repository, und checkout/restore kopieren in die jeweils andere Richtung zurück. git status und git diff sind letztlich nur Vergleichsoperationen zwischen genau zwei dieser drei Bereiche. Wer dieses Modell verinnerlicht, kann jeden Git-Befehl anhand einer einzigen Frage einordnen: Welcher Bereich wird gelesen, und welcher wird beschrieben?

Git-Grundlagen: Die drei Bereiche auf einen Blick

Working Directory

Der sichtbare Ordner auf der Festplatte. Änderungen landen hier zuerst, unabhängig von Git.

Staging Area (Index)

.git/index speichert, was der nächste Commit enthalten wird. git add befüllt sie gezielt.

Repository & HEAD

Unveränderliche Snapshots unter .git/objects. HEAD zeigt auf den letzten Commit des aktuellen Branches.

Bewegung zwischen den Bereichen

add (WD zu Index), commit (Index zu Repo), restore/checkout (zurück).

11. FAQ: Working Directory, Staging Area, Repository

1Was ist der Unterschied zwischen Working Directory, Staging Area und Repository?
Working Directory sind die echten Dateien auf der Festplatte. Staging Area (Index) legt fest, was der nächste Commit enthält. Repository speichert alle Commits als unveränderliche Snapshots.
2Warum ist git add ein extra Schritt?
Er entkoppelt "was wurde verändert" von "was soll ein Commit werden". So lassen sich mit git add -p gezielt einzelne Zeilen für fokussierte Commits auswählen.
3Was macht git commit technisch mit dem Index?
Erstellt einen vollständigen Tree-Snapshot des Index, referenziert den Elterncommit und bewegt den Branch-Zeiger. Unveränderte Dateien erzeugen keine neuen Blobs.
4Wie sehe ich, was im Staging Area liegt?
git status zeigt Changes to be committed. Für Zeilendetails: git diff --staged vergleicht Index gegen HEAD.
5git diff vs. git diff --staged?
git diff vergleicht Working Directory gegen Index. git diff --staged vergleicht Index gegen HEAD, also den letzten Commit.
6Ist git checkout -- datei.txt gefährlich?
Ja. Er kopiert die Index-Version zurück ins Working Directory und überschreibt dabei unwiderruflich nicht gestagte lokale Änderungen.
7git restore vs. git restore --staged?
restore kopiert Index zu Working Directory (verwirft lokale Änderungen). restore --staged kopiert HEAD in den Index (unstaged, WD bleibt unverändert).
8Was machen soft, mixed und hard bei reset?
soft bewegt nur HEAD. mixed bewegt zusätzlich den Index. hard überschreibt zusätzlich das Working Directory und kann Daten unwiderruflich löschen.
9Ist Staging Area dasselbe wie Index?
Ja, beide Begriffe bezeichnen dieselbe Datei .git/index und werden in der Git-Dokumentation synonym verwendet.
10Was bedeutet detached HEAD?
HEAD zeigt direkt auf einen Commit statt auf einen Branch. Neue Commits sind möglich, aber ohne Branch-Zeiger nach dem Wechsel schwer wiederzufinden.