Git: Commit zurücknehmen — reset, revert, reflog

Welcher Befehl den letzten Commit zurücknimmt, hängt an einer einzigen Frage: Liegt der Commit nur bei Ihnen, oder ist er schon gepusht? Lokal nimmt git reset den Commit weg — --soft behält Ihre Änderungen, --hard löscht sie; geht es nur um die Nachricht oder eine vergessene Datei, reicht git commit --amend. Ist der Commit schon geteilt, schreibt git revert einen Gegen-Commit und lässt die Geschichte stehen. Und wenn Sie zu viel zurückgenommen haben, holt git reflog den Stand von vorher wieder. Alle Befehle und Ausgaben in diesem Beitrag sind am 29. Oktober 2026 mit Git 2.55.0 in einem Wegwerf-Repository ausgeführt; die Hashes stammen aus demselben Lauf.

Die Entscheidung in einer Tabelle

Lage Befehl Was mit Ihren Änderungen passiert
Commit nur lokal, Änderungen sollen vorgemerkt bleiben git reset --soft HEAD~1 bleiben, stehen im Index
Commit nur lokal, Änderungen sollen bleiben, aber nicht vorgemerkt git reset HEAD~1 bleiben im Arbeitsverzeichnis, Index geleert
Commit nur lokal, Änderungen sollen weg git reset --hard HEAD~1 werden überschrieben, neue Dateien verschwinden
Nur die Nachricht falsch oder eine Datei vergessen git commit --amend bleiben, der Commit bekommt einen neuen Hash
Commit schon gepusht oder geteilt git revert <hash> nichts, es entsteht ein zusätzlicher Gegen-Commit
Sie haben zu viel zurückgenommen git reflog, dann git reset --hard <hash> der Stand von vorher kommt zurück

Der Ausgangsstand für alles Folgende sind drei Commits:

$ git log --oneline
5e4e55e Rabattcode 20 Prozent
8b6716f Preisliste eingebaut
c469881 Startseite angelegt

Fall 1: Der Commit liegt nur bei Ihnen

git reset [<mode>] <commit> ändert laut Referenz, auf welchen Commit HEAD zeigt. Der Modus entscheidet, was mit Index und Arbeitsverzeichnis geschieht — und genau da verlieren die meisten Arbeit:

Modus HEAD Index Arbeitsverzeichnis
--soft verschoben unverändert unverändert
--mixed (Vorgabe) verschoben auf den neuen HEAD gesetzt unverändert
--hard verschoben auf den neuen HEAD gesetzt überschrieben

Mit --soft bleibt alles vorgemerkt, was im Commit steckte. Das ist der Griff, wenn Sie denselben Inhalt anders committen wollen:

$ git reset --soft HEAD~1
$ git status --short
M  index.html
A  style.css

--mixed ist die Vorgabe, Sie können den Schalter also weglassen. Git meldet dann von sich aus, was nicht mehr vorgemerkt ist — und style.css, das es vor dem Commit noch nicht gab, ist jetzt wieder unversioniert:

$ git reset HEAD~1
Unstaged changes after reset:
M	index.html
$ git status --short
 M index.html
?? style.css

--hard überschreibt laut Dokumentation alle Dateien mit der Fassung aus dem Zielcommit und entfernt versionierte Dateien, die es dort nicht gibt. Im Beispiel verschwindet style.css wirklich von der Platte:

$ git reset --hard HEAD~1
HEAD is now at 8b6716f Preisliste eingebaut
$ git status --short
$ ls
index.html

HEAD~1 und HEAD^ meinen hier dasselbe — beide bezeichnen laut gitrevisions den ersten Eltern-Commit, und HEAD^ ist gleichbedeutend mit HEAD^1 und HEAD~1. Erst an einem Merge-Commit laufen sie auseinander, weil ^2 die zweite eingebrachte Seite meint, ~2 dagegen den Großeltern-Commit.

Wenn nur die Nachricht oder eine Datei fehlt

Dafür gibt es keinen Reset. git commit --amend ersetzt die Spitze des aktuellen Zweigs durch einen neuen Commit; die Nachricht des alten dient als Vorlage. Vergessene Datei nachtragen:

$ git add preise.json
$ git commit --amend --no-edit
[main 8d9e8a8] Rabattcode 20 Prozent
 Date: Thu Oct 29 09:20:00 2026 +0100
 3 files changed, 3 insertions(+)
 create mode 100644 preise.json
 create mode 100644 style.css

Nur die Nachricht korrigieren:

$ git commit --amend -m "Rabattcode 20 Prozent eingebaut"
[main 14fae66] Rabattcode 20 Prozent eingebaut
 Date: Thu Oct 29 09:20:00 2026 +0100
 2 files changed, 2 insertions(+)
 create mode 100644 style.css

Beachten Sie die Hashes: aus 5e4e55e wird 8d9e8a8 beziehungsweise 14fae66. Ein Amend ändert keinen Commit, es ersetzt ihn. Deshalb warnt die Referenz ausdrücklich davor, einen schon veröffentlichten Commit zu amenden — damit gilt derselbe Vorbehalt wie für reset auf einem geteilten Zweig.

Fall 2: Der Commit ist schon gepusht

Dann lassen Sie die Geschichte in Ruhe. git revert nimmt laut Dokumentation die Änderung eines vorhandenen Commits zurück und schreibt dafür einen neuen Commit:

$ git revert --no-edit HEAD
[main d733b09] Revert "Rabattcode 20 Prozent"
 Date: Thu Oct 29 09:30:00 2026 +0100
 2 files changed, 2 deletions(-)
 delete mode 100644 style.css
$ git log --oneline
d733b09 Revert "Rabattcode 20 Prozent"
5e4e55e Rabattcode 20 Prozent
8b6716f Preisliste eingebaut
c469881 Startseite angelegt

Der fehlerhafte Commit bleibt also stehen, seine Wirkung ist aber weg. Das Ergebnis darf jeder pushen, es ist ein gewöhnlicher Fast-Forward. Drei Dinge aus der Praxis:

  • Das Arbeitsverzeichnis muss sauber sein. Sonst bricht der Befehl mit error: Your local changes to the following files would be overwritten by merge ab.
  • Einen Merge-Commit lehnt Git ohne Angabe der Hauptlinie ab: error: commit … is a merge but no -m option was given. -m 1 nimmt in der Regel die Seite, auf der Sie stehen.
  • -n wendet die Rücknahme nur auf Index und Arbeitsverzeichnis an, ohne zu committen — praktisch, um mehrere Reverts zu einem Commit zusammenzufassen.

Die naheliegende Abkürzung — reset --hard und danach git push --force — ist auf einem geteilten Zweig ein Fehler. Die Git-Dokumentation schreibt zu --force, dass der Schalter die Sicherheitsprüfungen abschaltet und das entfernte Repository Commits verlieren kann. Konkret: Wer Ihren alten Stand schon gezogen und darauf weitergearbeitet hat, verliert diese Commits. Wenn es ohne Force nicht geht, nehmen Sie --force-with-lease; der Push greift nur, solange der entfernte Zweig noch auf dem Commit steht, den Sie erwarten. Für den umgekehrten Fall — eine Arbeitskopie zwangsweise auf den Remote-Stand ziehen, samt git clean für unversionierte Dateien — haben wir einen eigenen Beitrag: git pull –force erzwingen.

Fall 3: Sie haben zu viel zurückgenommen

Das reflog hält fest, wann die Spitzen von Zweigen und anderen Referenzen im lokalen Repository aktualisiert wurden — auch dann, wenn der alte Stand aus der Geschichte verschwunden ist. Nach einem Reset um zwei Commits:

$ git reset --hard HEAD~2
HEAD is now at c469881 Startseite angelegt
$ git reflog
c469881 HEAD@{0}: reset: moving to HEAD~2
5e4e55e HEAD@{1}: commit: Rabattcode 20 Prozent
8b6716f HEAD@{2}: commit: Preisliste eingebaut
c469881 HEAD@{3}: commit (initial): Startseite angelegt

5e4e55e ist der Stand von vorher. Zwei Wege zurück — der erste ist der sichere, weil er nichts überschreibt:

$ git branch rettung 5e4e55e
$ git reset --hard 5e4e55e
HEAD is now at 5e4e55e Rabattcode 20 Prozent

Statt des Hashes geht auch die Kurzschreibweise aus der Tabelle: HEAD@{1} ist laut gitrevisions der vorige Wert der Referenz.

Wie lange das funktioniert, steht in der Git-Referenz: gc.reflogExpire entfernt Einträge, die älter als 90 Tage sind, gc.reflogExpireUnreachable solche, die älter als 30 Tage und vom aktuellen Zweigende nicht erreichbar sind. Die 30 Tage sind die Frist, die hier zählt — genau solche Einträge entstehen laut Dokumentation durch git commit --amend und git rebase. Zwei Einschränkungen, die regelmäßig überraschen: Was nie committet war, steht in keinem reflog; dafür brauchen Sie vorher git stash. Und in einem Bare-Repository gibt es gar kein reflog, weil core.logAllRefUpdates dort laut Referenz standardmäßig auf false steht — auf dem Server hilft das reflog also nicht.

Dass eine verlorene Stunde Arbeit in einem Repository fast immer noch irgendwo liegt, ist der Grund, warum jedes Projekt bei uns im Git liegt, auch das kleine. Wie wir Anwendungen entwickeln und betreuen, steht unter Webentwicklung.

Quellen

Alle Seiten der offiziellen Git-Dokumentation am 29. Oktober 2026 abgerufen; die Vorgabewerte zusätzlich in der mit Git 2.55.0 ausgelieferten Handbuchseite git-config(1) geprüft.

  • git reset: Synopsis, --mixed als Vorgabe, Verhalten von --soft, --mixed und --hard gegenüber Index und Arbeitsverzeichnis, Entfernen versionierter Dateien durch --hard: git-scm.com/docs/git-reset
  • git revert: neuer Commit statt Geschichtsänderung, sauberes Arbeitsverzeichnis als Voraussetzung, -m für Merge-Commits, -n, --no-edit: git-scm.com/docs/git-revert
  • git commit --amend: ersetzt die Spitze des Zweigs durch einen neuen Commit, Warnung bei schon veröffentlichten Commits, --no-edit: git-scm.com/docs/git-commit
  • git reflog: Aufzeichnung der Aktualisierungen von Referenzen, show als Vorgabe-Unterbefehl mit HEAD, --expire und --expire-unreachable: git-scm.com/docs/git-reflog
  • gc.reflogExpire 90 Tage, gc.reflogExpireUnreachable 30 Tage, Herkunft der nicht erreichbaren Einträge aus commit --amend und rebase: git-scm.com/docs/git-gc, Abschnitt Configuration, sowie git-config(1) aus Git 2.55.0
  • core.logAllRefUpdates: standardmäßig true mit Arbeitsverzeichnis, false im Bare-Repository: git-config(1) aus Git 2.55.0, git-scm.com/docs/git-config
  • HEAD^, HEAD~<n>, Gleichung rev~3 = rev^^^ = rev^1^1^1, Reflog-Schreibweise <ref>@{<n>}: git-scm.com/docs/gitrevisions
  • git push --force schaltet die Sicherheitsprüfungen ab und kann Commits im entfernten Repository verlieren, --force-with-lease als Absicherung: git-scm.com/docs/git-push

Häufige Fragen

Wie nehme ich den letzten Commit zurück und behalte die Änderungen?

Mit git reset --soft HEAD~1. Die Git-Dokumentation beschreibt diesen Modus so, dass Arbeitsverzeichnis und Index unverändert bleiben — Ihre Änderungen stehen danach also wieder vorgemerkt bereit, nur der Commit ist weg. Soll der Index zusätzlich geleert werden, nehmen Sie git reset HEAD~1; --mixed ist die Vorgabe und muss nicht geschrieben werden. Finger weg von --hard, solange Sie die Änderungen behalten wollen: dieser Modus überschreibt die Dateien im Arbeitsverzeichnis.

Was ist der Unterschied zwischen reset und revert?

git reset verschiebt den Zweig auf einen älteren Commit, der zurückgenommene Commit ist danach nicht mehr Teil der Geschichte. git revert lässt die Geschichte stehen und schreibt laut Dokumentation einen neuen Commit, der die Änderung des alten rückwärts anwendet. Praktische Regel: reset für Commits, die nur bei Ihnen liegen, revert für alles, was schon gepusht oder anders geteilt ist. Nur revert lässt sich ohne Nebenwirkung für andere pushen.

Kann ich einen schon gepushten Commit löschen?

Technisch ja, mit reset und anschließendem push --force — aber auf einem geteilten Zweig sollten Sie das nicht tun. Die Git-Dokumentation sagt zu --force ausdrücklich, dass der Schalter die Sicherheitsprüfungen abschaltet und das entfernte Repository Commits verlieren kann. Hat jemand auf Ihrem alten Stand weitergearbeitet, geht dessen Arbeit dabei verloren. Der richtige Befehl auf einem geteilten Zweig ist git revert. Wenn Sie wirklich force pushen müssen, nehmen Sie mindestens --force-with-lease: der Push bricht ab, sobald sich der entfernte Zweig seit Ihrem letzten Fetch bewegt hat.

Wie lange finde ich einen Commit im reflog wieder?

Die Vorgabewerte stehen in der Git-Referenz: gc.reflogExpire entfernt Einträge, die älter sind als 90 Tage, und gc.reflogExpireUnreachable entfernt Einträge, die älter als 30 Tage und vom aktuellen Zweigende nicht erreichbar sind. Die kürzere Frist ist die, die Sie betrifft — genau solche Einträge entstehen laut Dokumentation durch git commit --amend und git rebase. Beide Werte lassen sich auf never setzen. In einem Bare-Repository gibt es gar kein reflog, weil core.logAllRefUpdates dort laut Referenz standardmäßig auf false steht.

HEAD~1 oder HEAD^ — was ist der Unterschied?

Für den letzten Commit keiner: beide Suffixe bezeichnen laut gitrevisions den ersten Eltern-Commit, und HEAD^ ist dasselbe wie HEAD^1 und HEAD~1. Unterschiedlich werden sie erst bei Zahlen größer eins und nur an Merge-Commits. HEAD^2 ist der zweite Eltern-Commit, also die eingebrachte Seite des Merge. HEAD~2 ist der Großeltern-Commit entlang der ersten Eltern. Die Dokumentation schreibt das als Gleichung: rev~3 ist dasselbe wie rev^^^ und wie rev^1^1^1.

Fragen zu diesem Thema?

Wir unterstützen Sie bei SEO, KI-Einführung und E-Commerce.

Projekt besprechen →