W3docs

git reflog

Detaillierte Informationen zum git reflog-Befehl: Reflog-Referenzen, Unterbefehle, zeitbasierte Reflogs und Beispiele zur Wiederherstellung.

Der Befehl git reflog ist dein Sicherheitsnetz. Er zeichnet jede Änderung an lokalen Referenzen auf — Branches, HEAD und Stashes — damit du Commits wiederherstellen kannst, die nach einem Reset, Rebase, Amend oder einem gelöschten Branch verschwunden zu sein scheinen. Diese Seite erklärt, was das Reflog speichert, wie die name@{n}-Syntax zu lesen ist, wie Einträge nach Zeit gefiltert werden, welche Unterbefehle verfügbar sind und wie „verlorene" Commits vollständig wiederhergestellt werden.

Was das Reflog ist

Eine Referenz (oder „Ref") ist ein Zeiger auf einen Commit — HEAD, ein Branch-Tip wie main oder ein Stash-Eintrag. Viele Git-Operationen verschieben diese Zeiger: Jedes git commit, checkout, merge, rebase oder reset aktualisiert, worauf eine Ref zeigt. Das Reflog („Referenz-Log") zeichnet diese Geschichte der Bewegungen auf.

Das ist wichtig, weil Git Commits fast nie sofort löscht. Wenn eine Operation wie ein Hard-Reset oder ein Rebase einen Commit von jedem Branch oder Tag unerreichbar macht, lebt das Commit-Objekt noch immer in deinem Repository, und das Reflog hält weiterhin einen Zeiger darauf. Solange dieser Reflog-Eintrag existiert, kannst du den Commit zurückholen.

git reflog

Info

Das Reflog ist strikt lokal und pro Klon. Es wird nie gepusht oder gefetcht, daher hat ein frischer Klon ein leeres Reflog. Wenn du den Verlauf umschreibst und einen Commit verlierst, kannst du ihn nur auf dem Gerät wiederherstellen, auf dem die Arbeit durchgeführt wurde.

Grundlegende Verwendung

Die einfachste Form benötigt keine Argumente:

git reflog

Dies ist eine Abkürzung für die Anzeige des Reflogs von HEAD:

git reflog show HEAD

Die Ausgabe listet jede Position auf, die HEAD innehatte, die neueste zuerst:

a32556a HEAD@{0}: commit: migrating content
ab371fd HEAD@{1}: commit: adding git reflog outline
23a491a HEAD@{2}: checkout: moving from stage to feature/solver
7b119cb HEAD@{3}: checkout: moving from feature/solver to stage
56a183a HEAD@{4}: commit: changing color scheme
7a2aa71 HEAD@{5}: commit: adding more color palettes
a56322b HEAD@{6}: commit: adding color tool package

Lies jede Zeile als drei Teile:

  • a32556a — der abgekürzte Commit-Hash, auf den HEAD zeigte.
  • HEAD@{0} — der Reflog-Selektor. @{0} ist die aktuellste Position, @{1} die davor, und so weiter, rückwärts in der Zeit zählend.
  • commit: migrating content — die Aktion, die die Ref verschoben hat, plus ihre Nachricht.

Das Aktionslabel zeigt dir wie die Ref verschoben wurde (commit, checkout, merge, rebase -i, reset), was das Reflog als schrittweise Verlaufsanzeige deiner lokalen Aktionen lesbar macht.

Reflog-Referenzen

Standardmäßig zeigt git reflog das Reflog von HEAD, das dem aktuell ausgecheckten Branch folgt. Aber jede Ref führt ihr eigenes Reflog, und du kannst auf jede davon mit der name@{qualifier}-Syntax zugreifen.

So siehst du das Reflog für alle Referenzen auf einmal:

git reflog show --all

Übergib einen Branch-Namen, um nur den Verlauf dieses Branches zu untersuchen. Unten das Reflog für test_branch:

git reflog show test_branch
32a591f test_branch@{0}: commit: add snippets
23bae4a test_branch@{1}: commit (initial): initial commit

Beachte den Unterschied: HEAD@{1} bedeutet „wo HEAD vor einem Schritt war", während test_branch@{1} bedeutet „wo test_branch selbst vor einem Schritt war". Diese Unterscheidung ermöglicht es dir, einen Branch-Tip wiederherzustellen, den ein Hard-Reset oder ein erzwungenes Update verschoben hat.

Du kannst auch das Reflog für den git stash lesen:

git reflog stash
0d44de3 stash@{0}: WIP on git_reflog: a567574 adding Vue.js

Zeitbasierte Reflogs

Jeder Reflog-Eintrag hat einen angehängten Zeitstempel. Diese können als Qualifizierer in der Git-Ref-Zeigersyntax verwendet werden, um Git-Reflogs nach Zeit zu filtern. Hier sind einige Beispiele für Zeitqualifizierer:

  • 1.minute.ago
  • 1.hour.ago
  • 1.day.ago
  • yesterday
  • 1.week.ago
  • 1.month.ago
  • 1.year.ago
  • 2011-05-17.09:00:00

Du kannst Qualifizierer kombinieren (z. B. 1.week.3.hours.ago) und Pluralformen verwenden (z. B. 5.hours.ago). Eine zeitqualifizierte Ref kann an andere Git-Befehle übergeben werden, nicht nur an git reflog:

git diff master@{0} master@{1.week.ago}

Dies zeigt ein Diff des aktuellen master gegenüber dem Stand von master vor einer Woche.

Warnung

Ein Zeitqualifizierer wird gegen das Reflog aufgelöst, nicht gegen Commit-Daten. master@{1.week.ago} bedeutet „der Commit, auf den master vor einer Woche auf diesem Gerät zeigte", was sich vom „vor einer Woche erstellten Commit" unterscheiden kann. Bei einem frischen Klon ohne Reflog-Verlauf fällt Git auf den aktuellen Tip zurück und gibt möglicherweise eine Warnung aus, dass das Log zu kurz ist.

Unterbefehle von git reflog

Git reflog akzeptiert mehrere Argumente, die als Unterbefehle fungieren. Diese werden nachfolgend beschrieben.

git reflog show

git reflog show ist das Standardverhalten und selbst ein Alias für git log -g --abbrev-commit --pretty=oneline. Diese beiden Befehle sind gleichwertig:

git reflog master@{0}
git reflog show master@{0}

git reflog expire

git reflog expire bereinigt alte oder unerreichbare Reflog-Einträge. Da das Entfernen von Einträgen Commits wirklich unwiederbringlich machen kann, führst du es selten manuell aus — Git führt es automatisch während git gc aus. Standardmäßig laufen erreichbare Einträge nach 90 Tagen ab (gc.reflogExpire) und unerreichbare nach 30 Tagen (gc.reflogExpireUnreachable). So erzwingst du einen benutzerdefinierten Ablauf:

git reflog expire --expire=1.day.ago --all

git reflog delete

git reflog delete entfernt einen bestimmten Reflog-Eintrag anhand seines Selektors. Wie expire birgt es ein echtes Risiko, die Wiederherstellbarkeit zu verlieren, und wird im Alltag selten benötigt:

git reflog delete HEAD@{1}
Gefahr

Sobald ein Reflog-Eintrag abläuft oder gelöscht wird, wird der Commit, auf den er zeigte, wirklich unerreichbar und beim nächsten Ausführen von git gc entfernt. Behandle expire und delete als Bereinigungstools, nicht als Rückgängig-Tools.

Verlorene Commits wiederherstellen

Commits gehen in Git nie wirklich verloren, auch nicht bei verlaufsumschreibenden Operationen — und das Reflog ist der Weg, sie zurückzuholen. Angenommen, git log --pretty=oneline sieht so aus:

2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commit

Angenommen, wir committen neue Änderungen in dieses Repository:

# make changes to HEAD
git commit -am "API changes"

Das Log sieht jetzt so aus:

37656e19d4e4f1a9b419f57850c8f1974f871b07 API changes
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commit

Als nächstes starten wir einen interaktiven Rebase gegen master:

git rebase -i origin/master

Während des Rebase markieren wir Commits mit der s (squash)-Aktion, um sie in den neuesten „API changes"-Commit zu falten. Danach ist die Ausgabe von git log auf Folgendes reduziert:

40d8a1237656e19d4e4f1a9b419f57850c8f1974 API changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit

Die squashten Commits scheinen weg zu sein. Aber das Reflog zeichnet noch immer jede Position auf, die HEAD während des Rebase innehatte:

git reflog
37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog
37656e1 HEAD@{1}: rebase -i (start): checkout origin/master
37656e1 HEAD@{2}: commit: API changes

HEAD@{2} ist der Zustand kurz vor dem Start des Rebase. Übergib diesen Selektor an git reset, um dorthin zurückzuspulen:

git reset --hard HEAD@{2}

Dies verschiebt HEAD zurück zum „API changes"-Commit vor dem Rebase und stellt alle gesquashten Commits wieder her. Verwende --hard, um auch den Working Tree auf diesen Zustand zurückzusetzen, oder lass es weg (git reset HEAD@{2}), um nur den Branch-Zeiger zu verschieben und die aktuellen Dateien beizubehalten.

Wann git reflog verwendet werden sollte

Greife auf das Reflog zurück, wenn eine Ref verschoben wurde und du sie zurückhaben möchtest:

  • Nach einem git reset --hard, der Commits verworfen hat, die du eigentlich gebraucht hättest.
  • Um Commits wiederherzustellen, die durch einen interaktiven Rebase, Amend oder Squash verwaist wurden.
  • Um einen Branch wiederherzustellen, den du mit git branch -D gelöscht hast (finde seinen letzten Tip im Reflog, dann git branch <name> <hash>).
  • Um herauszufinden, wo HEAD vor einer verwirrenden Folge von Checkouts oder Merges war.

Wenn der Commit jünger als das Ablaufzeitfenster des Reflogs ist (standardmäßig 90 Tage für erreichbare Einträge), ist er wiederherstellbar.

Verwandte Seiten

  • git reset — Refs auf einen Reflog-Eintrag verschieben, um Änderungen rückgängig zu machen.
  • git rebase — die umschreibende Operation, bei der das Reflog am häufigsten hilft.
  • git stash — Stashes haben ihr eigenes Reflog unter stash@{n}.
  • git log — die reguläre Verlaufsansicht; git log -g liest das Reflog.

Übungen

Übung
What are the correct statements about the `git reflog` command?
What are the correct statements about the `git reflog` command?
Was this page helpful?