Home > database >  Reverting a merge commit and merging a subset of commits back in later
Reverting a merge commit and merging a subset of commits back in later

Time:04-21

I have different release branches, let's say

  • release_0 (release last year)
  • release_1 (release this year)
  • release_2 (in development)
  • release_3 (in development)

release_2 branch was created a long time ago so it only contains release_0. release_3 branch was created from release_1.

I had the impression that release_2 should have the code of release_3 so I merged release_3 to release_2.
I was told later that release_2 will go live before release_3 so I reverted the merge commit from release_2 (and pushed the revert commit).
However as release_1 is already on production so I tried to merge the changes of release_1 to release_2 (release_2 is based on release_0). Unfortunately git says that 'Already up to date.'. It is because I merged release_3 to release_2 (which was reverted though) and release_3 already contains release_1.

What can I do in this situation? I read the https://stackoverflow.com/a/15737656/1269572 but it doesn't seem to be a solution as I need to remove the release_3 code from release_2.

Thank you!

CodePudding user response:

Essentially you are trying to put release_2 into a state that is equivalent to reverting part of the merge of release_3 into it. (So reverting the revert won't work.) This is unfortunately going to be messy unless you go with a clean hard reset of release_2 to before that merge. I'd consider the hard reset if the following conditions are true:

  1. There hasn't been much activity on release_2 since the undesirable merge of release_3.
  2. Whatever new commits that you need to keep on release_2 could be re-written without causing issues.
  3. It would be pretty straight forward to communicate to the team that you're resetting release_2 and you could provide the appropriate git rebase --onto command to any developer that has a branch in progress based off of it.

If you can't do the reset, then probably the simplest thing to do would be to make a new commit which represents all the changes on release_1 that aren't in release_2 yet and merge it in. (A patch would work too.) Something like this:

# On release_2, identify the commit before the merge; let's call it CBM
# Make a temp branch pointing to release_1
git switch -c release_1-contents origin/release_1 --no-track
# Reset soft to point to the merge-base of this branch and CBM
git reset --soft $(git merge-base HEAD CBM)
git commit -m "Squash contents of Release_1 content"
# now merge it into release_2
git switch release_2
git merge release_1-contents # use the commit message to explain what and why

Side Note: when trying to bring in commits again after a revert, the thing that matters is their commit ID; if you change them you can bring them in again. If there aren't too many commits on release_1 and you don't mind having duplicate commits in the repo forever, you could re-write them via cherry-picking a range or using rebase -f on release_1 to simply re-write the commit IDs, and then you can merge them in again. If there are many commits though I'd probably lean towards making a single squashed commit instead, as described above.

  •  Tags:  
  • git
  • Related