5

I created an experimental branch from master, and made four commits on the experimental branch. The master, in the mean time, still remains where it last was. Now, I want to merge my experimental branch in such a way that I will be able to easily undo this merge in future.

When I tried searching, the easiest way to undo a merge seems to me like git revert hash_of_merge_commit.

However, this only works when I get a merge commit hash when merging my master with experimental branch. In this case, since master's HEAD has not progressed, when I try to merge, I just get four new commits added to master, and this would mean that to undo this merge, I would need to manually remember and revert each of these individual commits in future.

Any better way to do this?

user229044
  • 232,980
  • 40
  • 330
  • 338
jeffreyveon
  • 13,400
  • 18
  • 79
  • 129

5 Answers5

15

The other answerers seem to be concerned with preventing this from happening in the first place. If a fast-forwarded merge has already occurred and been pushed, here's a solution:

  1. git checkout -b my-undo-branch
  2. git reflog show master - find the last commit before the merge
  3. git reset --keep SHA - using the SHA from the previous step

At this point, verify that this branch is in the state that you want master to be in. Now it's just a matter of taking the diff between those two branches and committing it to master:

  1. git checkout master
  2. git diff master my-undo-branch --no-prefix > patchfile
  3. patch -p0 < patchfile

Then, finally, delete patchfile, git add all the changes, and git commit them.

Trevor Burnham
  • 76,828
  • 33
  • 160
  • 196
  • Only real answer to the question. I'm quote astonished that there is no easier way to do this, though. – icyerasor Sep 03 '15 at 18:02
  • Seconded that this is the "real" answer. The original question assumes "no merge commit" - answering with "just use --no-ff" is actually an incorrect answer. – noahlz Jan 19 '17 at 20:54
  • Thanks! Does this leave a commit on master that can't be merged to develop because it would remove changes from there too? – cmart Dec 11 '19 at 17:45
0

You can merge with --no-ff to prevent fast-forward merges, which is how you "get four new commits added to master". When the branches haven't actually diverged, Git does a fast-forward merge and simply bumps the branch refs around. Preventing fast-forward merges will help you keep your branch history slightly more intact via obvious merge commits, though you won't be able to tell the name of the branch that commits were created on.

Otherwise there is no way short of inspecting the reflog. Git does not maintain branch information beyond the current 'tip' of each branch. There is no association between a commit and the branch that was checked out when that commit was created.

user229044
  • 232,980
  • 40
  • 330
  • 338
0

Undoing merges in general can be a tricky business. See http://progit.org/2010/03/02/undoing-merges.html or this other SO question for background.

What you might be looking for is:

git merge --no-ff

which will tell Git that it should create a merge commit even if it doesn't have to, as in this case.

Community
  • 1
  • 1
Emil Sit
  • 22,894
  • 7
  • 53
  • 75
0

You should merge without fast-forwarding, by passing --no-ff to the merge command.

This way a new commit is always created and you'll be able to revert it.

Generally merging feature branches should be always done non-fast-forward, making integration of your feature clear in the history of master branch.

CharlesB
  • 86,532
  • 28
  • 194
  • 218
0

I would revisit your branching strategy and introduce "throwaway" branches. That is, branches that may be used by your CI server or just you to see if things work. You should not be afraid of scrapping them. You may tag that branch before it's scrapped if you like to preserve what was attempted.

More on this here:

https://plus.google.com/109096274754593704906/posts/R4qkeyRadLR

user229044
  • 232,980
  • 40
  • 330
  • 338
Adam Dymitruk
  • 124,556
  • 26
  • 146
  • 141