7

I have finished a lengthy merge of a devel branch onto master, then I realised it should have been a devel update instead, meaning the direction should be master -> devel. Is it possible to change the destination of the commit, so that the arrow is pointing from master to devel?

note: The resulting changes in files would be exactly same for both d->m and m->d. It's just the final destination (and arrow in history) which is wrong.

now: enter image description here desired: enter image description here

blue: master
red: devel

*Changes are not commited or pushed yet.

Recapitulation

  • I resolved all conflicts in a devel->master merge.
  • I haven't commited or pushed the changes.
  • Changes are made on top of master.
  • I need to apply the resolved conflicts in a master->devel direction.
Qwerty
  • 29,062
  • 22
  • 108
  • 136

4 Answers4

7

Reverting a merge on the branch is as simple as determining which commit was the previous one.

First, checkout on the branch you want to modify. It's a git-golden-rule: you can only modify the branch you're on.

git checkout master

Then, figure out the previous-master commit it, and force master back into its previous state

git reset --hard <previous-commit-id>

Finally, do your merge right

git checkout devel
git merge master

What you could also do, if you want to be lazy, is invert branch states.

You still need to find master's previous commit-id.

Then:

git checkout devel
git reset --hard master
git checkout master
git reset --hard <previous-commit-id>
Supernovah
  • 1,946
  • 12
  • 34
  • 50
blue112
  • 52,634
  • 3
  • 45
  • 54
  • I haven't commited nor pushed it yet, but I don't want to do the lengthy merge all again (it was a difficult one), since I would have made it exactly the same. – Qwerty Jul 28 '15 at 09:13
  • Can I possibly stash the finished merge, initiate `master -> devel` merge, discard conflicts, apply stash and commit? – Qwerty Jul 28 '15 at 09:14
  • Edited my answer @Qwerty – blue112 Jul 28 '15 at 09:19
  • I am kinda lost in it. When do I commit and push the changes? Let's recapitulate: 1) I resolved all conflicts in a devel->master merge. 2) I haven't commited or pushed the changes. 3) Changes are made on master. 4) I need to apply the resolved conflicts in a master->devel direction. – Qwerty Jul 28 '15 at 09:22
  • @blue112 as per my knowledge If there are merge conflicts, you have to fix them again when merging into correct branch, if theres better way someone please tell. – Vishwanath Jul 28 '15 at 09:29
  • Oh, you haven't commited your conflicts. Commit them on master, and the apply the procedure on the second part on my post. – blue112 Jul 28 '15 at 09:31
  • Okay, thank you, the second part really worked!! ..and I didn't have to make the merge again. – Qwerty Jul 28 '15 at 10:37
  • @Qwerty: FYI if you want to avoid repeatedly fixing merge conflicts, you might be able to use `git rerere` to reuse recorded resolutions – Hasturkun Jul 28 '15 at 11:50
  • Thank for the solution (first part)! Really help also after committing and pushing. – Adiel May 29 '16 at 07:10
2

It's actually a bit simpler than anwser of @blue112 . First commit the master locally.

git checkout master
git commit

This will create a shared commit for master and devel. Then switch to devel and merge it also with master. This will result in a fast-forward merge as there aren't any conflicts left.

git checkout devel
git merge master

It should be save to push devel now.

git push devel origin/devel

Now revert master back to its previous commit, so it remains as it was before the merge:

git checkout master
git reset --hard <previous-commit-id>

Workspace should be clean and safe now.

0

I would force the devel branch to take on current master's HEAD, and then reset master's HEAD back one commit. Like so:

git checkout master    
git branch -f devel HEAD          # force "devel" to equal current "master"
git branch -u origin/devel devel  # set "devel"'s upstream tracking.
git reset --hard HEAD~1           # set "master" back one commit.

And then if you like what you see...

git checkout devel
git push
Julius Musseau
  • 4,037
  • 23
  • 27
0

To avoid losing any work, given your exact situation, I would force the devel branch to take on current master's HEAD, and then reset master's HEAD back one commit. Like so:

git checkout master    
git branch -f devel HEAD          # force "devel" to equal current "master"
git branch -u origin/devel devel  # set "devel"'s upstream tracking.
git reset --hard HEAD~1           # set "master" back one commit.

And then if you like what you see...

git checkout devel
git push
Julius Musseau
  • 4,037
  • 23
  • 27