Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

Git Revert a Merge Commit: The -m Flag and the Trap Afterwards

Sean

Platform Writer

Aug 26, 2026
8 min read

git revert -m 1 <merge-commit> undoes a merge. The -m 1 names which parent to treat as the mainline — almost always 1, the branch you merged into. The important part is what happens next: Git now considers those changes permanently rejected, so merging that branch again brings back nothing.

Git Revert a Merge Commit: The -m Flag and the Trap Afterwards

Reverting a merge is the standard way to back out a bad feature that has already been pushed, and it works well. The part that catches teams out arrives weeks later, when the feature has been fixed and someone merges the branch again — and the code does not come back.

That is not a bug. It is a direct consequence of what a revert records, and there is a specific procedure for getting the changes back.

Table of contents

Why the -m flag is required

A revert creates a new commit that applies the inverse of an existing one. For an ordinary commit that is unambiguous — there is one parent, so there is one “before” state to compare against.

A merge commit has two parents, so “undo this” has two possible meanings, and Git will not guess:

error: commit a1b2c3d is a merge but no -m option was given.

Look at the parents:

git show --no-patch a1b2c3d
# commit a1b2c3d
# Merge: 9f8e7d6 4c3b2a1
#        ^parent 1  ^parent 2

Parent 1 is the branch you were on when you merged — usually main. Parent 2 is the branch that was merged in.

-m 1 means: keep the mainline, discard what the feature branch brought. That is what people want in essentially every case.

git revert -m 1 a1b2c3d

-m 2 would keep the feature branch’s changes and discard the mainline’s — which is almost never the intent, and is worth being careful about because both are valid commands and only one is correct.

The trap: re-merging brings back nothing

This is the part worth understanding before you need it.

Git’s merge algorithm works from the commit graph, not from file contents. Once the feature branch is merged, its commits are ancestors of main forever — reverting the merge adds a commit that undoes the changes, but does not remove those ancestors.

So when you merge the branch again, Git looks at the graph, sees every commit is already an ancestor, and concludes there is nothing to do. The revert stays. The feature does not come back.

The fix is to revert the revert:

# find the revert commit
git log --oneline --grep="Revert"

# undo it -- this is an ordinary commit, so no -m needed
git revert <revert-commit-hash>

That restores the original changes, and then any new commits on the feature branch merge normally on top of them.

The sequence in full, which is worth reading once:

  1. Merge feature → main. Changes are live.
  2. Revert the merge with -m 1. Changes are gone; commits remain ancestors.
  3. Fix the feature on its branch.
  4. Revert the revert on main. Original changes return.
  5. Merge the branch again. The new fixes come in on top.

Revert versus reset, and when each is correct

The deciding question is whether the commit has been pushed.

Revert adds a new commit that undoes an old one. History is preserved and everyone’s clone stays consistent. This is the only safe option for anything on a shared branch.

Reset moves the branch pointer, removing commits from history. Fine on a local branch nobody has pulled. On a shared branch it requires a force push, and everyone else’s next pull produces a mess.

# pushed -- use revert
git revert -m 1 <merge-commit>
git push

# local only, never pushed -- reset is cleaner
git reset --hard HEAD~1

The reset version leaves a tidier history, which is genuinely worth something on a branch you own. The revert version leaves a record of the decision, which is worth more on a branch other people build on.

A middle option people forget: if the merge was the very last thing you did and you have not pushed, git reset --merge HEAD~1 undoes it while preserving any uncommitted work in your tree, which --hard would discard.

Reverting only part of a merge

Sometimes the merge brought in ten commits and one of them is the problem. Reverting the whole merge is a large hammer for that.

Revert the individual commit instead:

git log --oneline main..feature-branch     # what the merge brought in
git revert <the-one-bad-commit>

This has none of the re-merge complications, because you are reverting an ordinary commit rather than the merge itself. The branch’s other commits stay in place and future merges behave normally.

For several adjacent commits, revert a range — note that the range is exclusive at the start:

git revert --no-commit abc123..def456
git commit -m "Revert the broken batch"

--no-commit stages all the reversals without committing each one, so you get a single tidy commit rather than a run of them.

If a revert hits a conflict — likely when later commits touched the same lines — resolve it like any merge conflict and continue:

git status                 # see the conflicted files
# edit them
git add <resolved-files>
git revert --continue
# or, to back out entirely
git revert --abort

Deciding quickly under pressure

This usually comes up when something is broken in production, which is a bad time to be reasoning about parent numbers. A short decision path:

  • Broken and pushed, need it gone nowgit revert -m 1 <merge>. Ship it, fix properly afterwards.
  • Broken, not pushedgit reset --hard HEAD~1. Cleaner, no history to explain.
  • One commit in the merge is bad — revert that commit alone, not the merge.
  • Previously reverted, now fixed — revert the revert, then merge again.

And the thing worth doing before any of them, which takes two seconds and has saved a great many people:

git switch -c before-revert && git switch -

That leaves a branch pointing at the current state. Whatever happens next, the position you started from has a name.

How this fits the rest of the stack

The reason reverting a merge is fiddly is that Git is optimising for a property worth having: history that everyone shares and nobody rewrites. Undoing a change becomes a new fact rather than an erasure, which is exactly what you want when several people depend on the same branch.

Deployments benefit from the same property. If every release corresponds to a commit and previous deploys remain available, backing out a bad release is selecting a known-good build rather than reconstructing one under pressure. RunxBuild keeps build and runtime logs per deploy and supports rolling back to a previous one, so the recovery path does not depend on getting a Git command right at the worst possible moment. The RunxBuild hosting calculator shows what the service, database and storage cost together.

Useful related references:

FAQ

What does -m 1 mean in git revert?

It selects which parent of the merge commit to treat as the mainline. Parent 1 is the branch you merged into, usually main, and parent 2 is the branch that was merged in. -m 1 keeps the mainline and discards what the feature branch brought, which is what you want in nearly every case.

Why does re-merging a branch after reverting bring back nothing?

Git decides what to merge from the commit graph. The branch’s commits are still ancestors of main after a revert, so Git sees nothing new to bring in. Revert the revert commit first — it is an ordinary commit, so no -m is needed — and the changes return.

Should I revert or reset a merge commit?

Revert if the merge has been pushed, because it preserves history and does not require a force push. Reset if the merge is local only and nobody has pulled it, which leaves a cleaner history. The deciding question is always whether anyone else has the commit.

Can I revert just one commit from a merge?

Yes, and it is often the better option. Find it with git log --oneline main..feature-branch and revert that commit directly. Because you are reverting an ordinary commit rather than the merge, the re-merge complications do not apply.

What happens if a revert causes conflicts?

Resolve it as you would any merge conflict — edit the files, git add them, then git revert --continue. Use git revert --abort to back out entirely. Conflicts are likely when later commits modified the same lines the revert is trying to undo.

#git revert a merge commit#git#git revert#merge#version control