Home > database >  git merge reverted but the changes needed
git merge reverted but the changes needed

Time:12-19

I have a feature branch, let's call it A, and a main line, let's call it B, where we deliver. The problem is the following:

  1. Branch A was many commits ahead of branch B, nothing extraordinary so far. So I did a merge from branch A to B.
  2. Then I noticed, this is not what I wanted as I suspect the automatic merges were not alright.
  3. I did a revert for the merge, which was ok, the changes merged disappeared.
  4. I only want to have the code state of branch A in branch B; consequently, I removed the directories and files locally in branch B and wanted to do the merge from branch A again, which does not work anymore as git perceives that the merge has already been done. My second idea is to check out branch A in branch B but I don't know how as normal checkouts from the remote repository will go into the corresponding branches: A in A and B in B.

Any idea how I could check out branch A in branch B? Remark: there are no changes in the main line since starting this feature branch A, so what I need is A in branch B. Thanks for any solutions in advance.

Would git fetch <remote> <remoteBranch>:<localBranch> do this?

git fetch origin A:B
git push origin B

CodePudding user response:

Let's start by visualizing your situation:

                            branch B
o---o---o---------------M---W
         \             /
          o---o---o---o
                      branch A

I'm going to assume that you have pushed both the merge commit M and its reverse W, so you can no longer rewrite the history of branch B.

Reverting a faulty merge

If you want to bring in the changes from branch A into B after the first merge has been reverted, you have to revert the revert by reverting commit W:

git switch B
git revert W

However, you said that you don't want to create a commit right away, but rather you'd like the changes made in branch A to be in the working directory while you're on B. You can do that by using the --no-commit option of git-revert:

git switch B
git revert --no-commit W

This will bring back the changes from branch A into your working directory.

If you're interested in understanding why this situation occurs in the first place, I think Linus himself explains it best:

Reverting a regular commit just effectively undoes what that commit did, and is fairly straightforward. But reverting a merge commit also undoes the data that the commit changed, but it does absolutely nothing to the effects on history that the merge had.

So the merge will still exist, and it will still be seen as joining the two branches together, and future merges will see that merge as the last shared state - and the revert that reverted the merge brought in will not affect that at all.

So a "revert" undoes the data changes, but it's very much not an "undo" in the sense that it doesn't undo the effects of a commit on the repository history.

So if you think of "revert" as "undo", then you're going to always miss this part of reverts. Yes, it undoes the data, but no, it doesn't undo history.

CodePudding user response:

You can trick git into thinking that the merged branch was not merged by just rewriting its history

git checkout $( git-merge-base feature-branch upstream-branch-before-the-merge )
git cherry-pick HEAD..feature-branch # assuming it is a straight line
# now you have a history just like the original branch but, to git, this is not merged
# let's set the pointer over here
git branch -f feature-branch

If you try to merge the new branch, git should be fine with it.

  • Related