Zurück zum Blog

Git Revert vs Reset: Was rettet deine History?

15. September 2026

TL;DR: git revert fügt einen neuen Commit hinzu, der einen alten zurücknimmt — die History bleibt erhalten, sicher auf Branches, die andere schon gepullt haben. git reset bewegt den Branch-Pointer rückwärts — die History wird umgeschrieben, nur sicher bei Commits, die du nicht gepusht hast. Revert auf geteilten Branches, Reset beim lokalen Aufräumen. reset --hard löscht zusätzlich uncommittete Änderungen im Working Tree; das ist der Befehl, der echte Arbeit frisst.

Was ist der Unterschied zwischen git revert und git reset?

Beide lassen dein Projekt aussehen, als wäre ein vergangener Commit nie passiert. Sie sind sich nur uneinig über das Wie:

  • git revert <sha> berechnet den inversen Patch eines Commits und committet ihn. Deine History wächst um einen Commit, der sagt „nimm den da zurück”. Der schlechte Commit bleibt im Log, gefolgt von seiner Annullierung. Die SHAs von allem anderen bleiben unberührt.
  • git reset <sha> bewegt den Pointer des aktuellen Branches auf <sha>. Die Commits danach werden abgehängt — noch in der Objektdatenbank, bis der Garbage Collector kommt, aber von keinem Branch und keinem git log mehr erreichbar.

Der eine schreibt nichts um, der andere tut so, als wäre nichts gewesen. Diese eine Eigenschaft entscheidet, welche Situation welchen Befehl verlangt:

# Demo: ein Wegwerf-Repo, das direkt läuft
git init /tmp/revert-vs-reset && cd /tmp/revert-vs-reset
echo one > file.txt && git add . && git commit -m "one"
echo two > file.txt && git add . && git commit -m "two"

# Revert: die History behält beide Commits, plus einen dritten, der "two" zurücknimmt
git revert --no-edit HEAD
git log --oneline        # 3 Commits: revert, two, one

# Reset: der Branch-Pointer wandert zurück, "two" verschwindet aus dem Log
git reset --hard HEAD~1
git log --oneline        # 1 Commit: one

Beides ausführen und git log ansehen — die Asymmetrie ist die gesamte Antwort.

Was machen git reset —soft, —mixed und —hard wirklich?

Die drei Modi steuern, wo deine Änderungen überleben, nachdem der Pointer sich bewegt hat:

ModusBranch-PointerStaging AreaWorking TreeDeine Änderungen
--softwandert zurückbleibt gestagedunberührtkomplett erhalten
--mixed (Standard)wandert zurückungestagedunberührterhalten, ungestaged
--hardwandert zurückzurückgesetztzurückgesetztgelöscht

Konkrete Lesarten dieser Tabelle:

  • git reset --soft HEAD~1 — „Ich habe zu früh committet.” Alles geht zurück in die Staging Area, bereit zum erneuten Committen, vielleicht zusammen mit mehr Arbeit.
  • git reset HEAD~1 (mixed) — „Ich habe die falschen Dateien gestaged.” Die Änderungen überleben im Working Tree, nichts ist gestaged. Kombiniere das mit git remove untracked files, wenn auch herumliegende Dateien weg sollen.
  • git reset --hard HEAD~1 — „Dieser Commit und meine uncommitteten Änderungen sind Müll.” Git fragt nicht zweimal; für den Working-Tree-Teil gibt es kein Undo, außer du hast ihn vorher gestasht oder committet.

revert hat keine Modi, weil es nie etwas zerstört — es fügt nur einen Ausgleichs-Commit hinzu.

Wann solltest du git revert statt git reset verwenden?

Eine Frage stellen: Hat jemand sonst diesen Commit schon gepullt? Wenn ja, fällt reset flach.

Einen Branch umschreiben, auf dem andere aufbauen, schreibt die geteilte History um. Ihr nächstes Pull trifft auf divergierende Branches, und der „Fix” ist meist ein Force-Push, der aus deinem Fehler das Problem aller macht. Revert hängt einen normalen Commit an, darum merged ein schlichtes git pull für alle sauber — deshalb ist revert die Standardantwort auf main und bei GitHub-Pull-Requests, wo es den „Revert”-Knopf genau deshalb gibt, weil man die History eines gemergten PR nicht umschreiben kann.

Reset ist für das Fenster vor dem Teilen: der Commit von vor dreißig Sekunden, der Staging-Fehler, der lokale Experiment-Branch. Lebt die einzige Kopie der Arbeit auf deiner Maschine, darfst du die History umsortieren — das ist der ganze Sinn des Pre-Push-Fensters.

Es gibt den Mittelfall: du hast auf deinen eigenen Feature-Branch gepusht, und niemand baut darauf. Ein Force-Push nach reset ist dort sozial akzeptabel, aber revert kostet trotzdem weniger Abstimmung. Force-Pushes den Branches vorbehalten, die dir allein gehören.

Ist git revert sicherer als git reset für geteilte Branches?

Ja, strukturell — nicht nur per Konvention:

  • Revert erzeugt einen gewöhnlichen Commit; CI läuft darauf, das Diff ist reviewbar, und git log erklärt dem zukünftigen Ich, warum die Änderung verschwand.
  • Reset verwirft den Zwischenstand still. Niemand, der später reviewt, sieht, was wann zurückgenommen wurde, denn das Log zeigt eine gerade Linie, die es nie enthielt.

Zwei praktische scharfe Kanten:

  • Das Reverten eines Merge-Commits braucht git revert -m 1 <sha> (die Linie des ersten Parents behalten). Ohne -m verweigert git und überlässt dir das Fehlerlesen.
  • Revert ist keine Zeitmaschine: Er nimmt das Diff eines Commits zurück. Haben spätere Commits dieselben Zeilen berührt, darfst du Konflikte auflösen — git sagt dir damit, dass das Undo verstrickt ist. Nützliche Information, keine Fehlfunktion.

Speziell fürs Zurücknehmen des allerletzten Commits — mit oder ohne Behalten der Änderungen — sind die Optionen in git undo last commit: keep the changes aufbereitet.

Wo passt git restore ins Bild?

git restore (und git switch, sein Gegenstück) kam mit git 2.23 und übernahm die Jobs, die reset wegen seiner Namensüberladung schlecht erledigte:

AufgabeAlter WegKlarer Weg
Working-Tree-Änderungen einer Datei verwerfengit checkout -- file / git reset --hardgit restore file
Eine Datei unstagengit reset HEAD filegit restore --staged file
Branch auf anderen Commit bewegengit reset <sha>git reset <sha> (kein Ersatz — das bleibt)

Die moderne Aufteilung lautet also: restore repariert Dateien, reset bewegt Branches, revert nimmt veröffentlichte Commits zurück. Autocomplete zeigt: Leute suchen „git revert vs reset vs restore” gemeinsam, und das aus gutem Grund — es ist ein mentales Modell, verteilt auf drei Befehle. Die alten git checkout-Formen funktionieren überall weiter; die neuen verhindern nur, dass du einen ganzen Branch in den Aktenvernichter schickst, obwohl du eine Datei unstagen wolltest.

Wenn dein Ziel ist, einen guten Commit nach vorn zu kopieren statt einen schlechten zu tilgen, ist das Sache von cherry-pick — siehe git cherry-pick: multiple commits, branches, conflicts.

Die Entscheidung in Kürze

  1. Commit ist öffentlich (gepusht, andere haben gepullt) → git revert <sha>.
  2. Commit ist nur lokal, du willst ihn neu machen → git reset --soft oder --mixed und neu committen.
  3. Nur lokal, und er soll samt dem uncommitteten Chaos weg → git reset --hard, nach einem ehrlichen Blick darauf, was sonst noch im Working Tree liegt.
  4. Eine Datei verhunzt → git restore <file> und den Branch in Ruhe lassen.

Der einzig wirklich gefährliche Eintrag in dieser Liste ist --hard — alles andere lässt sich mit git reflog zurückreden. Die permanenten Verluste in git sind eng umrissen und verlangen meist, dass du sie explizit tippst; die Angewohnheit, die sich lohnt, ist eine halbe Sekunde Innehalten vor --hard, nicht das Meiden von gits scharfen Werkzeugen.

— mrsaynothing

Get the next one by email

One email per post. No spam, no algorithms.

self-hosted · no third parties · one-click unsubscribe

what is this?

Systemd-Dienst startet nicht? So behebst du es

Sie mögen die Artikel? Genau so baue ich beruflich. anheuern