link64
link64

Reputation: 1976

Reverting a reverted merge in Git

I have a bit of a situation on the main branch in my repository.

A developer mistakingly pushed a PR from our develop branch directly into main and pushed to remote. We've applied policies so that this cannot happen again.

After this, we reversed this PR by utilising the 'Revert PR' feature in Azure DevOps, which created a branch, undid all the changes, and then merged it all back into main. So far so good.

In the meantime, we've also had to apply some hotfixes to the main branch. When attempting to roll these changes back up to develop, I've realised that the revert commit will also go back up, meaning we will lose changes in develop.

I've also now realised that when we do a PR from dev to main, these previously pushed changes will not be merged back down again.

How do I sort out the situation so that I do not lose the feature changes when merging hotfixes back into develop and also ensure that the feature comes back to main the next time we do a correct PR?

My assumption is that I need to revert the revert (git revert -m 1 ), but is there a better way?

Upvotes: 3

Views: 821

Answers (2)

matt
matt

Reputation: 535944

You effectively reverted a merge, but that does not erase the merge. This is a classic situation. See https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt

As that article explains (in the words of Linus, who wrote Git in the first place, so he ought to know), if you revert a merge commit, you can never again merge the commits from the second parent, because they were already merged; the revert of the merge commit removes its effects on the first parent ("so far so good", as you say) , but it does not undo the fact of the merge, whose topology remains part of the history.

Your best bet is to construct that PR afresh, entirely from scratch, perhaps by cherry picking (or rebasing) its commits, so as to get the same effect using different commits. That will give you a new PR that you can merge all the way to main.

Upvotes: 4

Jay
Jay

Reputation: 3950

Situation:

  • dev was merged into main ("merge X")
  • on main: "merge X" was reverted ("commit Y")

Suggestion:

  • merge main back into dev
  • then on dev: git revert <commit Y> (new "commit Z")
    Note: -m 1 is not needed here, because the revert "commit Y" itself is just a regular commit, not a merge.

Result:

  • Hotfixes from main are now also on dev
  • dev has not lost (the once reverted) changes, because "commit Z" restored them
  • If dev gets merged into main again, the once reverted changes will be applied again (because they now come from "commit Z")

Upvotes: 2

Related Questions