Git Revert a Merge Commit: How to Undo a Merge Safely (With -m Explained)
You merged a branch (maybe a PR), pushed it, and now you need to undo it. The first instinct is often git reset --hard — but on a shared branch that can break teammates’ clones and CI.
The safe fix is usually:
# Safe on shared branches (creates a new commit)
git revert -m 1 <merge-commit-hash>
git revert <merge> without -m, Git will refuse because it doesn’t know which parent is the “mainline” to keep.
Table of Contents
1. Quick decision: reset vs revert (and squash/ff merges)
Use this table to pick the right undo method in seconds.
| Situation | Do this | Why |
|---|---|---|
| Merged locally, not pushed | git reset --hard ORIG_HEAD |
Moves your branch pointer back before the merge commit. |
| Merged and pushed to a shared branch | git revert -m 1 <merge> |
Creates a new commit that undoes the merge without rewriting history. |
| You did a squash merge (no merge commit) | git revert <squash-commit> |
Squash merge produces a normal commit; revert it like any other. |
| You did a fast-forward merge (no merge commit) | Revert the commits (or reset if not pushed) | Fast-forward merges don’t create a merge commit to revert. |
git revert.
2. What is a merge commit? (and why -m exists)
A regular commit has one parent. A merge commit has two parents (or more for octopus merges). Git literally stores pointers to both histories.
That’s why reverting a merge is ambiguous: Git must know which parent should be treated as the “mainline” (the history you want to keep).
To see a merge commit’s parents:
# Shows parents (look for "parent" lines)
git show --no-patch --pretty=raw <merge-commit-hash>
You can also quickly find recent merges:
# Recent merge commits
git log --merges --oneline -n 20
# On main: show the merge commits that actually landed on main
git log --first-parent --merges --oneline -n 20
main) and parent 2 is the merged branch. But always check the parents on the exact merge commit you’re reverting.
3. Understanding git revert -m (mainline parent)
The -m flag means mainline. It tells Git which parent should be considered the mainline when generating the inverse patch.
git revert -m 1 <merge>keeps parent 1, and undoes the changes introduced by the other parent(s).git revert -m 2 <merge>keeps parent 2, and undoes the changes introduced by parent 1.
main and pushed. Parent 1 is usually main — so -m 1 is usually correct.
If you want to preview the revert before committing it:
# Apply the revert but let me inspect before committing
git revert -m 1 --no-commit <merge>
# Inspect changes
git status
git diff
# Commit when satisfied
git commit -m "Revert merge <merge>"
4. Step-by-step: revert a pushed merge commit
Scenario: a PR was merged into main, deployed, and you need to roll it back safely.
Step 1: Find the merge commit hash
# Fetch latest main from origin
git fetch origin
git switch main
git pull --ff-only
# List merges on main
git log --first-parent --merges --oneline -n 20
Pick the merge commit you want to undo (the one with two parents).
Step 2: Verify the parents (so you choose the right -m)
git show --no-patch --pretty=raw <merge>
Confirm which parent is main (or the branch you want to keep). Then choose -m accordingly.
Step 3: Revert the merge
# Most common for "undo PR merge into main"
git revert -m 1 <merge>
If conflicts happen, resolve them like a normal merge conflict, then finish the revert:
git status
# edit files to resolve
git add -A
git revert --continue
git reset --hard on pushed history unless your team explicitly agrees to rewrite history and force-push.
5. How to re-merge later (revert the revert)
A classic surprise: after reverting a merge commit, re-merging the same branch later can produce “Already up to date” or reintroduce only part of the changes.
That’s because Git uses commit graph history. If the merge commit exists in history (even if it was reverted), Git may treat the branch as already merged.
Two common ways to re-merge:
Option A: revert the revert
This is the most straightforward when you want the exact same changes back.
# Find the revert commit you created
git log --oneline -n 20
# Revert the revert (re-applies the changes)
git revert <revert-commit-hash>
# Now you can merge again (if needed)
git merge feature-branch
Option B: cherry-pick the needed commits
If you only want some commits back (or the branch moved on), cherry-pick can be cleaner.
# Copy individual fixes back onto main
git cherry-pick <commit1> <commit2>
If you want the “copy a commit vs undo a commit” mental model, see: Git Cherry-Pick vs Revert.
6. Undo a merge that isn’t pushed yet
If you merged locally and haven’t pushed, you can usually just move your branch pointer back.
# ORIG_HEAD typically points to where HEAD was before the merge
git reset --hard ORIG_HEAD
If the merge is still in progress (you haven’t committed the merge yet), abort instead:
git merge --abort
--hard discards uncommitted work. If you have local changes you need to keep, stash or commit them first.
7. Troubleshooting & gotchas
“error: commit <hash> is a merge but no -m option was given”
You’re reverting a merge commit. Choose the mainline parent:
git revert -m 1 <merge>
You chose the wrong -m value
If you reverted with -m 2 but should have used -m 1 (or vice versa), you can fix it by reverting the revert commit and redoing the correct revert:
# Undo the bad revert
git revert <bad-revert-commit>
# Revert the merge correctly
git revert -m 1 <merge>
There is no merge commit (squash / fast-forward)
If your platform used squash merge or fast-forward, there is no merge commit to revert. In that case, revert the resulting commit(s) like normal commits.
Reverting creates conflicts
This is normal when code moved after the merge. Resolve conflicts, then run:
git add -A
git revert --continue
FAQ
Can I undo a merged pull request without force-pushing?
Yes. Find the merge commit on main and use git revert -m 1 <merge>. This creates a new commit, so it is safe on shared branches.
What if I merged main into my feature branch and want to undo that?
You can still revert the merge commit with git revert -m, but the correct parent might be different. Inspect the merge commit’s parents and choose -m based on which parent represents the branch state you want to keep.
Is it better to revert the merge commit or revert the individual commits?
If the merge introduced many commits and you want to undo the entire change set, reverting the merge commit is usually simpler. If you only need to undo one specific commit, reverting that commit alone can be cleaner.
If you’re dealing with other undo situations (reset vs revert vs restore, reflog recovery), see: Git Undo: Reset, Revert & Restore.