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 mergeab. - Einen Merge-Commit lehnt Git ohne Angabe der Hauptlinie ab:
error: commit … is a merge but no -m option was given.-m 1nimmt in der Regel die Seite, auf der Sie stehen. -nwendet 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,--mixedals Vorgabe, Verhalten von--soft,--mixedund--hardgegenüber Index und Arbeitsverzeichnis, Entfernen versionierter Dateien durch--hard: git-scm.com/docs/git-resetgit revert: neuer Commit statt Geschichtsänderung, sauberes Arbeitsverzeichnis als Voraussetzung,-mfür Merge-Commits,-n,--no-edit: git-scm.com/docs/git-revertgit commit --amend: ersetzt die Spitze des Zweigs durch einen neuen Commit, Warnung bei schon veröffentlichten Commits,--no-edit: git-scm.com/docs/git-commitgit reflog: Aufzeichnung der Aktualisierungen von Referenzen,showals Vorgabe-Unterbefehl mitHEAD,--expireund--expire-unreachable: git-scm.com/docs/git-refloggc.reflogExpire90 Tage,gc.reflogExpireUnreachable30 Tage, Herkunft der nicht erreichbaren Einträge auscommit --amendundrebase: git-scm.com/docs/git-gc, Abschnitt Configuration, sowiegit-config(1)aus Git 2.55.0core.logAllRefUpdates: standardmäßigtruemit Arbeitsverzeichnis,falseim Bare-Repository:git-config(1)aus Git 2.55.0, git-scm.com/docs/git-configHEAD^,HEAD~<n>, Gleichungrev~3=rev^^^=rev^1^1^1, Reflog-Schreibweise<ref>@{<n>}: git-scm.com/docs/gitrevisionsgit push --forceschaltet die Sicherheitsprüfungen ab und kann Commits im entfernten Repository verlieren,--force-with-leaseals 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.