2

First, I have to apologise - there are quite a number of 'how to undo a merge' questions on SO, but I'm so new at git that I really don't understand how to adapt the solutions them to my situation (though I'm sure they can be).

I have two branches, versionA and versionB. I made some changes in versionA and merged them into versionB, which is fine because the changes made in versionA are forwards compatible. Then, I think I must have accidentally merged versionB back into versionA, which is not fine because versionB is not backwards-compatible to versionA.

How can I undo this?

To make things clearer, this is what I've done:

versionA C--C--C--C'--M2
          \          /
           \        /
versionB C--M--C--C*

M: merged versionA into versionB. this is fine.
M2: accidentally merged versionB back into versionA

This is what I want:

versionA C--C--C--C'
          \         
           \       
versionB C--M--C--C*

If I were on Mercurial I'd do hg rollback and all would be fine, or I'd hg update C' and make future commits off there for the versionA branch, although this would leave M2 as a dead dangling head (hence I'd prefer the rollback method).

What is the git way to scrub that last commit M2 from the versionA branch? (All changes have been pushed).

mathematical.coffee
  • 55,977
  • 11
  • 154
  • 194

1 Answers1

1

You need to find the commit of the merge.

To find the merge commit try: git log versionA ^versionB --ancestry-path --merges

The needed commit is the very last commit.

git revert -m 1 commit_hash

But please read up on Linus' write up: http://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.txt

Also see: Which commit hash to undo a pushed merge using git-revert?

Community
  • 1
  • 1
Peter van der Does
  • 14,018
  • 4
  • 38
  • 42
  • Thanks! Could I request some further explanation? What would my history look like with the first option? `M2` is a dangling head and further commits to `versionA` all come off `C'`? (i.e. my history for `versionA` looks like a single continuous line with one little (dead) leaf `M2` hanging off it?) Also, could you explain what `git reset HEAD^ --hard` does? I a look at `git help reset` but it does not explain what the `^` after `HEAD` means (although it uses it in the examples). I'm guessing it means "the commit prior to `HEAD`"? – mathematical.coffee Jul 20 '12 at 01:14
  • Finally, if I do the second version (scrubbing the history), what will happen if someone else already has pulled `M2` into their history? And similarly, if a future person pulls the repository will they see `M2` at all? – mathematical.coffee Jul 20 '12 at 01:15
  • To answer the first couple of questions - I found the explanation for `HEAD^` in `git help revisions`. And based off `git help revert`, I think my new `versionA` history will be `C--C--C--C'--M2--M2'`, where `M2'` says "reverted changes of M2". The other questions (will the `reset HEAD^ --hard` screw over anyone who has already checked out `M2`) still stand. – mathematical.coffee Jul 20 '12 at 01:23
  • You better do this before anybody has fetched the repo, or people might not like you. I also just realized it's a merge that want to revert, that's a bit more complicated. I'll edit my answer – Peter van der Does Jul 20 '12 at 01:28
  • Thanks for the update - but isn't the commit of the merge `M2`? (or do you mean `C'`?) Also, your command does not return anything at all. – mathematical.coffee Jul 20 '12 at 01:34
  • Thanks. I read Linus' explanation and it appears that the "commit of the merge" is `M2` (which I know). Also, I do not need to revert the revert as Linus suggests, because `versionB` is *never* supposed to be merged into `versionA`, since `versionB` is not backwards compatible to `versionA` (as stated in the question). Hence I just need to do a single revert. cheers! – mathematical.coffee Jul 20 '12 at 01:42