0

Suppose the following git history (in chronological order):

master [I]------------------------[M2]---[MG]---[RV]---[MG2] dev \---[D1]----------[D2]----------/ / release \---[R1]-------------------------------/ 
  • The repo starts with an initial commit I.
  • A dev branch is created with one new commit D1.
  • A release branch is branched off of dev with a new commit R1.
  • A new commit is added to the dev branch (D2).
  • A new commit is added to the master branch (M2).
  • dev is merged into master (MG)
  • Uh oh! we didn't mean to do that... we revert the merge commit RV with -m 1 to specify that master should be considered the mainline
  • We had meant to merge release into master, so we do that now (MG2)

Oh no! Now the changes introduced in D1 are not present on master. I want them to be included (but I don't want D2's changes to be present). So my questions are:

  1. Assuming that I've just merged dev to master (MG), is there a command that I can use in place of git revert so that when I merge release into master I'll still have the changes from D1?
  2. Suppose I've already gone ahead with a merge from dev into master and a revert, is there a command I can use in place of git merge so that when I merge release into master I'll still have the changes from D1?

I'm aware that I could achieve this by doing a git reset --hard M2 on the master branch, but I want to avoid rewriting history if at all possible. It would also be great if a solution accounted for the possibility that additional "good" commits were added to the master branch between MG and RV or between RV and MG2.

3
  • Are you sure the changes in D1 are not in master? From your history it seems R1 contains the changes in D1, which should therefore be in MG2. Commented Nov 22, 2017 at 16:51
  • I doubted myself at first too, but the git docs have a note about the issue here: git-scm.com/docs/git-revert#git-revert---mainlineparent-number: "Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge." Commented Nov 22, 2017 at 17:39
  • The docs there actually link to a note by Linus about the issue, so my answer may be found there: git-scm.com/docs/howto/revert-a-faulty-merge.html Commented Nov 22, 2017 at 17:39

2 Answers 2

1

The solution proposed here (search for ADDENDUM) is to recreate an alternative to D1 (D1' below), so that its content is not ignored by later merges:

git checkout dev git rebase --no-ff I 

This should result in:

dev /---[D1']---------[D2'] master [I]------------------------[M2]---[MG]---[RV]---[MG2] \---[D1]----------[D2]----------/ / release \---[R1]-------------------------------/ 

You also need to recreate your release branch so that it starts at D1', then merge that to master:

git checkout release git rebase D1' git checkout master git merge release 

Result:

release /---[R1']---------------------------------\ dev /---[D1']---------[D2'] \ master [I]------------------------[M2]---[MG]--[RV]--[MG2]--[MG3] \---[D1]----------[D2]----------/ / \---[R1]-----------------------------/ 

Of course, if you've not pushed MG2, it might be a good idea to clean up before. This kind of history could easily confuse people in the future.

Sign up to request clarification or add additional context in comments.

Comments

0

I think you can use git cherry-pick to resolved your mistakes > https://git-scm.com/docs/git-cherry-pick

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.