29

So I made a pretty big mistake. I made a commit, pulled, merged (but messed up the code while doing so) and then pushed. I'd like to redo that merge and get the code right. Is there any way to do this?

I use bitbucket.

1
  • 14
    Just a note - this is actually on-topic on SO, and should not have been migrated. Try reading your own help pages sometime and note the software tools commonly used by programmers line. That said, it is also on-topic here - SwiftCore, don't feel bad that it was migrated, that was not your fault.
    – Bob
    Dec 21, 2013 at 10:23

6 Answers 6

21

Not sure if this is the "blessed" way to do it, but here's what I did to resolve the same problem without having to "force push" or anything gross like that.

Let's assume your history looks something like this (and M is the flubbed merge):

-A--B--C--M (master points here)
  \      /
   D----E

Running git checkout -b merge_fix <commit ID E> creates a branch before we made any mistakes:

-A--B--C--M (master points here)
  \      /
   D----E (HEAD and merge_fix point here)

Now, let's re-do the merge on our new branch. We can't just merge in master, so we need to manually pick the commit before our bad merge: git merge <commit ID C> Don't make the same mistakes you did last time!

-A--B--C--M (master points here)
  \      X
   D----E-G (HEAD and merge_fix point here)

Assuming that commit G looks good, now we want to sync up with the top of the master branch. This command tells git to ignore the changes that were made to master, and force our changes to become the merge result: git merge -s ours master

-A--B--C--M (master points here)
  \      X  \
   D----E-G--H (HEAD and merge_fix point here)

Finally, (again assuming that commit H looks good, we want to fast-forward master to include our fixed merge:

git checkout master
git merge merge_fix

This really just moves the master branch pointer to H, but I'll take the opportunity to clean up my ASCII art a bit:

-A--B--C--M--H (HEAD, master, and merge_fix all point here)
  \      X  /
   D----E--G

And there you have it! you've successfully re-done the merge without invalidating any history!

2
  • It should be noted that if any further commits were made beyond M before beginning to fix, their changes might be overwritten by this method. I've had success in preserving these changes by skipping git merge -s ours master, instead immediately doing git checkout master, then finally git merge -s resolve merge_fix. This alternate method works best if those further commits are not in conflict with merge_fix.
    – AgentRev
    Jul 30, 2020 at 6:23
  • @AgentRev the changes are not overwritten if the steps are followed like there are no additional commits beyond M, and git merge -s ours M is done with the "fubbed" commit M first. This step is basically just discarding M changes. And then it can be merged with master's HEAD. Feb 1, 2021 at 22:51
7

You can do it, like this:

  1. Reset to the commit before your merge.
  2. Perform the merge again
  3. Force push

That is:

git reset --hard SHA1
git merge branchname
git commit
git push --force remotename branchname

Just keep in mind that git push --force will rewrite whatever you had at the remote branch, and other people using that branch may be affected by this too. (Normally you should not do this.)

2
  • 7
    Just remember doing git push --force is not safe
    – Zepplock
    Dec 21, 2013 at 7:22
  • save alternative to git push --force is git push --force-with-lease; e.g. in the last step use git push --force-with-lease remotename branchname Nov 8, 2021 at 14:48
3

git merge --abort and then you can merge again

4
  • I just get a "there is no merge to abort" message
    – SwiftCore
    Dec 21, 2013 at 7:07
  • 3
    This can only be done when there are merge conflicts. Dec 21, 2013 at 7:21
  • why the minus one? this helped me.
    – swdev
    Jun 2, 2015 at 17:21
  • Because the question is about when you have already finished the merge (incorrectly) and pushed. Nov 8, 2019 at 20:37
0

try

git checkout . 
git merge --abort

this will undo any local changes during merge, and then revert back to pre-merge state. if you already did a commit or merge continue, you'll need to do the reset HEAD~ steps

0

I had a different, somewhat more complicated setup.

there's basically three starting points: (and the other solutions are all assuming either 1 or 2)

  1. redo-branch should be completely merged AND
    after the merge of redo-branch there have been no other merges
  2. redo-branch should be completely merged AND
    after the merge of redo-branch there have already been other merges, that should be kept
  3. redo-branch is a long-living branch to be repeatedly merged AND
    only a range of revision was part of the merge AND
    there have been other commits/merges on master after the failed merge (ouch)

a setup for (3) would be

---A--B--C--M   (master points here)
  /        /
-X--D-----E--Y  (that's the long-living redo-branch)
  1. you should be fine with solution https://superuser.com/a/691497/308385
  2. same solution as 1 might work
  3. let's get started :-)
# let's start on the last commit before the failed merge
git checkout redo-branch
git checkout -b D^1 new-branch-for-merge

# now let's pick all the revisions D through E
git cherry-pick D^1..E

# go to the target branch (master) and merge
git checkout master
git merge new-branch-for-merge
-1

Please check this hope it's useful for you

https://www.kernel.org/pub/software/scm/git/docs/howto/revert-branch-rebase.html
2
  • While this can answer OP question, link only answers are not well accepted on SO. You can however quote in your answer most relevant excerpts from the link.
    – alko
    Dec 21, 2013 at 9:54
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
    – Pranav 웃
    Dec 21, 2013 at 9:57

You must log in to answer this question.