# Das Reflog – deine Lebensversicherung bei Git-Unfällen 🛟

Das Reflog (Reference Log) ist eines der mächtigsten, aber am wenigsten bekannten Features von Git. Es ist buchstäblich dein Sicherheitsnetz, das dich vor fast jedem Git-Unfall retten kann – selbst wenn du denkst, du hättest Commits unwiederbringlich verloren.

---

## Was genau ist das Reflog?

Das Reflog ist ein **lokales Protokoll aller Bewegungen von Referenzen** (insbesondere HEAD) in deinem Repository. Jedes Mal, wenn sich HEAD bewegt – sei es durch einen Commit, Checkout, Reset, Rebase, Merge oder irgendeinen anderen Befehl – wird ein Eintrag im Reflog erstellt.

### Der entscheidende Unterschied zur normalen Historie

Die normale Git-Historie (die du mit `git log` siehst) zeigt dir nur die Commits, die von deinem aktuellen Branch aus erreichbar sind. Das Reflog hingegen protokolliert **jede Zustandsänderung**, unabhängig davon, ob die entsprechenden Commits noch von einem Branch referenziert werden oder nicht.

Stell dir das Reflog wie eine **Zeitmaschine** vor: Es merkt sich nicht nur, wo du jetzt bist, sondern auch jeden Ort, an dem du jemals warst – selbst wenn der Weg dorthin inzwischen „verschwunden" zu sein scheint.

### Was wird im Reflog gespeichert?

Jeder Reflog-Eintrag enthält folgende Informationen:

- **SHA-1-Hash** des Commits, auf den HEAD zu diesem Zeitpunkt zeigte
- **Aktion**, die die Bewegung ausgelöst hat (commit, checkout, reset, rebase, merge, etc.)
- **Zeitstempel** der Aktion
- **Nachricht** mit zusätzlichen Details (z.B. Commit-Message oder Branch-Name)

---

## Warum ist das Reflog deine „Lebensversicherung"? 🆘

In Git gibt es viele Situationen, in denen du denkst, du hättest Daten verloren:

1. **Harter Reset:** Du führst `git reset --hard HEAD~5` aus und merkst, dass du die falschen Commits gelöscht hast
2. **Fehlgeschlagener Rebase:** Ein Interactive Rebase geht schief und deine Commits scheinen verschwunden
3. **Branch gelöscht:** Du löschst versehentlich einen Branch, der noch nicht gemergt war
4. **Falscher Checkout:** Du wechselst den Branch und hast vergessen, Änderungen zu committen
5. **Amend-Unfall:** Du machst `git commit --amend` und überschreibst versehentlich einen wichtigen Commit

In all diesen Fällen gilt: **Die Commits sind nicht wirklich weg!** Sie sind nur nicht mehr von einem Branch aus erreichbar. Das Reflog hat sie jedoch noch protokolliert und kennt ihre SHA-1-Hashes.

### Die 90-Tage-Regel

Git behält Reflog-Einträge standardmäßig **90 Tage** lang (für erreichbare Commits) bzw. **30 Tage** (für nicht mehr erreichbare Commits). Erst danach werden sie bei einer Garbage Collection (`git gc`) endgültig entfernt. Du hast also ein großzügiges Zeitfenster, um Fehler zu korrigieren.

---

## Das Reflog in der Praxis – Kommandozeile

### Grundlegender Befehl

```bash
git reflog
```

Dieser Befehl zeigt dir die letzten Bewegungen von HEAD. Die Ausgabe sieht etwa so aus:

```
a1b2c3d (HEAD -> feature/login) HEAD@{0}: commit: Implementiere Login-Validierung
e4f5g6h HEAD@{1}: commit: Füge Login-Formular hinzu
i7j8k9l HEAD@{2}: checkout: moving from main to feature/login
m0n1o2p (main) HEAD@{3}: reset: moving to HEAD~3
q3r4s5t HEAD@{4}: commit: Wichtiger Commit den ich verloren glaubte
u6v7w8x HEAD@{5}: commit: Noch ein wichtiger Commit
y9z0a1b HEAD@{6}: commit: Der erste wichtige Commit
```

### Die Reflog-Syntax verstehen

Die Notation `HEAD@{n}` ist eine spezielle Referenz-Syntax:

- `HEAD@{0}` – der aktuelle Zustand von HEAD
- `HEAD@{1}` – der vorherige Zustand von HEAD
- `HEAD@{2}` – der Zustand davor
- usw.

Du kannst diese Notation auch mit Zeitangaben verwenden:

```bash
git reflog HEAD@{1.hour.ago}
git reflog HEAD@{yesterday}
git reflog HEAD@{2024-01-15}
```

### Detaillierte Reflog-Ansicht

Für mehr Details kannst du Optionen hinzufügen:

```bash
# Mit vollständigen Commit-Informationen
git reflog show --all

# Mit Datum und Uhrzeit
git reflog --date=iso

# Nur für einen bestimmten Branch
git reflog show feature/login
```

---

## Praktische Rettungsszenarien mit dem Reflog

### Szenario 1: Commits nach hartem Reset wiederherstellen

Du hast versehentlich einen harten Reset durchgeführt und wichtige Commits „verloren":

```bash
# Der fatale Befehl, der alles kaputt gemacht hat
git reset --hard HEAD~5

# Panik! Aber Ruhe bewahren – Reflog anschauen
git reflog
```

Die Ausgabe zeigt dir:

```
a1b2c3d (HEAD -> main) HEAD@{0}: reset: moving to HEAD~5
f8e9d0c HEAD@{1}: commit: Letzter wichtiger Commit
b2c3d4e HEAD@{2}: commit: Vorletzter wichtiger Commit
...
```

Jetzt kannst du zu dem Commit vor dem Reset zurückkehren:

```bash
# Entweder mit der Reflog-Referenz
git reset --hard HEAD@{1}

# Oder direkt mit dem SHA-Hash
git reset --hard f8e9d0c
```

### Szenario 2: Gelöschten Branch wiederherstellen

Du hast einen Branch gelöscht und merkst zu spät, dass er wichtige Arbeit enthielt:

```bash
# Der Fehler
git branch -D feature/wichtig

# Reflog zeigt den letzten Commit des Branches
git reflog | grep "feature/wichtig"
# Ausgabe: a1b2c3d HEAD@{5}: checkout: moving from feature/wichtig to main

# Branch wiederherstellen
git checkout -b feature/wichtig a1b2c3d
```

### Szenario 3: Nach fehlgeschlagenem Rebase zurück zum Ursprung

Ein Interactive Rebase ist schiefgegangen:

```bash
# Du hast das hier gemacht
git rebase -i HEAD~10
# Und dabei alles vermasselt...

# Reflog zeigt den Zustand vor dem Rebase
git reflog
# Ausgabe: 
# x1y2z3w (HEAD -> feature) HEAD@{0}: rebase (finish): ...
# ...
# a1b2c3d HEAD@{7}: rebase (start): checkout HEAD~10
# f8e9d0c HEAD@{8}: commit: Mein letzter sauberer Commit

# Zurück zum Zustand vor dem Rebase
git reset --hard HEAD@{8}
```

### Szenario 4: Versehentlich überschriebenen Commit nach Amend wiederherstellen

Du hast `git commit --amend` benutzt und dabei den ursprünglichen Commit überschrieben:

```bash
git reflog
# Ausgabe:
# a1b2c3d (HEAD -> main) HEAD@{0}: commit (amend): Neue Message
# f8e9d0c HEAD@{1}: commit: Ursprüngliche Message die ich behalten wollte

# Der ursprüngliche Commit existiert noch und kann wiederhergestellt werden
git cherry-pick f8e9d0c
# Oder wenn du komplett zurück willst:
git reset --hard f8e9d0c
```

---

## Das Reflog in PhpStorm nutzen 🖥️

PhpStorm bietet eine grafische Oberfläche für das Reflog, die besonders für visuelle Lerntypen hilfreich ist.

### Methode 1: Über das Git-Log-Fenster

1. Öffne das **Git-Tool-Fenster** (unten in PhpStorm) oder über *View → Tool Windows → Git*

2. Im **Log-Tab** siehst du normalerweise die Commit-Historie. Klicke auf das **Uhren-Symbol** (🕐) oder suche nach der Option *„Show Reflog"* in den Filter-Optionen

3. Alternativ kannst du im Suchfeld des Log-Fensters nach spezifischen Commits suchen, wenn du deren SHA-Hash aus dem Terminal-Reflog kennst

### Methode 2: Über das Terminal in PhpStorm

1. Öffne das **Terminal** in PhpStorm (*View → Tool Windows → Terminal* oder `Alt+F12`)

2. Führe dort `git reflog` aus – du bekommst die gleiche Ausgabe wie im externen Terminal

3. **Vorteil:** Du kannst SHA-Hashes direkt kopieren und in PhpStorms Git-Funktionen verwenden

### Methode 3: „Reset Current Branch to Here" nutzen

Wenn du im Git-Log einen bestimmten Commit gefunden hast (auch einen, der nur noch im Reflog existiert), kannst du ihn wiederherstellen:

1. **Rechtsklick** auf den Commit im Log-Fenster
2. Wähle *„Reset Current Branch to Here..."*
3. Wähle den Reset-Modus:
   - **Soft:** Behält alle Änderungen staged
   - **Mixed:** Behält Änderungen, aber unstaged
   - **Hard:** Verwirft alle Änderungen (Vorsicht!)

### Methode 4: Cherry-Pick für einzelne Commits

Wenn du nur einen bestimmten „verlorenen" Commit wiederhaben möchtest:

1. Finde den SHA-Hash im Reflog (Terminal: `git reflog`)
2. In PhpStorm: *Git → Uncommitted Changes → Cherry-Pick* (oder über das Log-Fenster)
3. Gib den SHA-Hash ein oder suche nach dem Commit

### Methode 5: Branch aus Reflog-Commit erstellen

1. Finde den SHA-Hash des gewünschten Commits
2. *Git → Branches → New Branch*
3. Im Dialog kannst du bei *„Starting point"* den SHA-Hash eingeben
4. Damit erstellst du einen neuen Branch, der auf den „verlorenen" Commit zeigt

---

## Das Reflog für verschiedene Referenzen

Das Reflog existiert nicht nur für HEAD, sondern für alle Referenzen in deinem Repository:

```bash
# Reflog für HEAD (Standard)
git reflog show HEAD

# Reflog für einen bestimmten Branch
git reflog show main
git reflog show feature/login

# Reflog für alle Referenzen
git reflog show --all
```

Dies ist besonders nützlich, wenn du wissen möchtest, wie sich ein bestimmter Branch im Laufe der Zeit entwickelt hat, auch über Resets und Force-Pushes hinweg.

---

## Wichtige Einschränkungen des Reflogs ⚠️

Trotz seiner Mächtigkeit hat das Reflog einige Grenzen, die du kennen solltest:

### Das Reflog ist lokal

Das Reflog wird **nicht** mit Remote-Repositories synchronisiert. Es existiert nur auf deinem lokalen Rechner. Das bedeutet:

- Wenn du dein Repository neu klonst, ist das Reflog leer
- Teammitglieder haben jeweils ihr eigenes, unabhängiges Reflog
- Du kannst das Reflog nicht nutzen, um Commits wiederherzustellen, die du nie lokal hattest

### Zeitliche Begrenzung

Reflog-Einträge werden nach einer gewissen Zeit gelöscht:

```bash
# Standard-Einstellungen anzeigen
git config gc.reflogExpire          # Standard: 90 Tage
git config gc.reflogExpireUnreachable   # Standard: 30 Tage

# Falls gewünscht: Längere Aufbewahrung konfigurieren
git config gc.reflogExpire "180 days"
git config gc.reflogExpireUnreachable "90 days"
```

### Garbage Collection beachten

Wenn `git gc` (Garbage Collection) läuft, können alte, nicht mehr referenzierte Commits tatsächlich gelöscht werden – aber nur, wenn sie auch aus dem Reflog abgelaufen sind:

```bash
# Manuelle Garbage Collection (normalerweise nicht nötig)
git gc

# Aggressive GC (kann alte Commits entfernen!)
git gc --aggressive --prune=now
```

---

## Fortgeschrittene Reflog-Techniken

### Commits in einem Zeitraum finden

```bash
# Alle Reflog-Einträge der letzten 2 Stunden
git reflog --since="2 hours ago"

# Reflog-Einträge zwischen zwei Zeitpunkten
git reflog --since="2024-01-01" --until="2024-01-15"
```

### Reflog mit Diff kombinieren

Du kannst dir anschauen, was sich zwischen zwei Reflog-Zuständen geändert hat:

```bash
# Diff zwischen aktuellem Zustand und Zustand vor 5 Aktionen
git diff HEAD@{5} HEAD@{0}

# Welche Dateien haben sich geändert?
git diff --name-only HEAD@{5} HEAD@{0}
```

### Reflog-Einträge als Grundlage für Branches

```bash
# Branch erstellen, der auf einen Reflog-Zustand zeigt
git branch recovery-branch HEAD@{10}

# Direkt zu einem Reflog-Zustand wechseln
git checkout HEAD@{10}  # Achtung: Detached HEAD!
```

---

## Zusammenfassung – Dein Reflog-Notfall-Spickzettel 📋

| Situation | Lösung |
|-----------|--------|
| Commits nach `reset --hard` verloren | `git reflog` → SHA finden → `git reset --hard <SHA>` |
| Branch versehentlich gelöscht | `git reflog` → letzten Commit des Branches finden → `git checkout -b <branch-name> <SHA>` |
| Rebase schiefgegangen | `git reflog` → Zustand vor Rebase finden → `git reset --hard HEAD@{n}` |
| Commit nach Amend überschrieben | `git reflog` → ursprünglichen Commit finden → `git cherry-pick <SHA>` |
| Wissen, was man vor X Stunden gemacht hat | `git reflog --since="X hours ago"` |

**Das Wichtigste zum Schluss:** Wenn etwas schiefgeht, **keine Panik!** Solange du nicht `git gc --prune=now` ausführst oder das Repository löschst, sind deine Commits mit sehr hoher Wahrscheinlichkeit noch da. Das Reflog ist dein Freund – lerne es kennen, bevor du es brauchst! 🛟