Revert and Unmerge
git revert and Unmerging Changes
After this page you can undo a published commit by adding a new commit, including a merge.
Revert writes history forward
cd ~/desk/desk-api
git switch main
git revert HEAD --no-edit
git log --oneline -3The bad commit is still in the graph. A new commit applies the inverse patch. Shared clones can fast-forward. This is the safe undo on main.
reset --hard HEAD~1 (local only) A ← B main
C still in reflog
revert HEAD (shared) A ← B ← C ← R main
R undoes C; C remains
--no-edit keeps Git’s default message (Revert "…"). Edit with git revert HEAD if you need a fix: subject.
Several commits
git revert --no-edit HEAD~2..HEADReverts newest first (the range is exclusive on the left). Conflicts: git add and git revert --continue, or git revert --abort.
Revert a merge commit
A merge has two parents. Git needs to know which parent is “the mainline” to diff against:
git revert -m 1 <merge-hash>-m 1 means “keep first parent’s tree; undo what the merged branch brought in.” -m 2 is the other parent (almost never what you want on main).
After reverting a merge, Git considers that feature’s commits already merged. Cherry-picking them back later can no-op. To re-land the feature, revert the revert, or rebase the feature into new hashes.
Revert vs reset vs restore
| Goal | Command | History |
|---|---|---|
| Throw away uncommitted edits | git restore |
Unchanged |
| Replace last unpublished commit | git commit --amend / reset |
Rewritten |
| Undo a published commit | git revert |
New commit |
git reset --hard on shared main is a force-push incident. Revert instead.
Un-merge without -m
If the merge was never pushed and is HEAD:
git reset --hard HEAD~1That moves main to first parent and drops the merge commit from the branch name. Only on a lab clone or an unpublished branch. Chapter 7 is reset in full. The merge commit stays in the reflog (chapter 17) until it expires.