By admin , 29 April 2026

Defining "bad merge"

A bad merge can mean: you merged the wrong branch, you resolved conflicts incorrectly, the merge introduced a regression, or you merged before review was complete. Each has a different fix. The key is acting fast and using the right tool.

Case 1: not yet pushed

If the merge is local-only, undo it cleanly:

git reset --hard ORIG_HEAD

ORIG_HEAD records the pre-merge HEAD; this command rewinds the branch to before the merge. Add HEAD@{1} if ORIG_HEAD has been overwritten.

Case 2: pushed, others have not pulled

If you can confirm no one pulled, force-push the rewind:

git reset --hard ORIG_HEAD
git push --force-with-lease

Coordinate via chat first. Force-push on shared branches is a teamwork activity.

Case 3: pushed, others have pulled

Now history rewriting is dangerous. Use revert instead:

git revert -m 1 <merge-sha>

-m 1 tells revert to undo the merge by reapplying main's pre-merge state, treating parent 1 as the canonical line. The result is a new commit that undoes the merge's effect.

Re-merging after a revert

The next gotcha: if you simply re-merge the original branch, Git considers it already merged and does nothing. To re-merge, first revert the revert:

git revert <revert-sha>
# or rebase the feature branch and merge again
git checkout feature/login
git rebase main
git checkout main
git merge feature/login

Case 4: bad conflict resolution

If the merge mechanics were correct but conflict resolution introduced bugs, fix forward with a regular commit:

git checkout main
# ...edit the affected files...
git commit -m "Fix conflict resolution from merge of feature/login"

Mark the original merge in the commit message for traceability.

Case 5: merged the wrong branch

Local-only:

git reset --hard ORIG_HEAD
git merge correct-branch

Already pushed: revert as in Case 3, then merge the correct branch.

Inspecting a merge

git log -1 --format=fuller --stat HEAD
git show -m HEAD                # show as separate diffs against each parent
git diff HEAD^1 HEAD             # what the merge added vs main side
git diff HEAD^2 HEAD             # what the merge added vs feature side

Avoiding bad merges

  • Always use --no-ff on long-lived branches; --ff-only on short ones.
  • Configure CI to run on the merge result, not just the branch tip.
  • Use git mergetool for tricky conflicts; eyeballing is error-prone.
  • Run tests immediately after every merge.

The recovery toolkit

  • ORIG_HEAD - automatically set before merges, resets, rebases.
  • git reflog - records every HEAD movement.
  • git revert -m - undo a merge by creating a new commit.
  • git push --force-with-lease - safer force push.

Bad merges feel catastrophic in the moment. They are not. Pause, identify which case applies, pick the right tool, and recover.