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: Harter Reset: Du führst git reset --hard HEAD~5 aus und merkst, dass du die falschen Commits gelöscht hast Fehlgeschlagener Rebase: Ein Interactive Rebase geht schief und deine Commits scheinen verschwunden Branch gelöscht: Du löschst versehentlich einen Branch, der noch nicht gemergt war Falscher Checkout: Du wechselst den Branch und hast vergessen, Änderungen zu committen 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 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: 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: # 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": # 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: # 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: # 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: # 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: 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 Öffne das Git-Tool-Fenster (unten in PhpStorm) oder über View → Tool Windows → Git 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 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 Öffne das Terminal in PhpStorm (View → Tool Windows → Terminal oder Alt+F12) Führe dort git reflog aus – du bekommst die gleiche Ausgabe wie im externen Terminal 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: Rechtsklick auf den Commit im Log-Fenster Wähle „Reset Current Branch to Here..." 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: Finde den SHA-Hash im Reflog (Terminal: git reflog) In PhpStorm: Git → Uncommitted Changes → Cherry-Pick (oder über das Log-Fenster) Gib den SHA-Hash ein oder suche nach dem Commit Methode 5: Branch aus Reflog-Commit erstellen Finde den SHA-Hash des gewünschten Commits Git → Branches → New Branch Im Dialog kannst du bei „Starting point" den SHA-Hash eingeben 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: # 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: # 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: # 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 # 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: # 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 # 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 Branch versehentlich gelöscht git reflog → letzten Commit des Branches finden → git checkout -b 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 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! 🛟