问题
I'm working with a repository where a merge was performed weeks ago which we just discovered used the --strategy=ours
flag (it was supposed to use the --strategy-option=ours flag), thus not applying any changes to HEAD. However, we need to have the changes applied. Git already recognizes the branch as being merged and the commits in the history of the branch.
This sort of merge can't be reverted using git revert -m ...
What would be the proper way of reverting and/or re-applying the merge to change the files?
master A - B - E - F - G ---> L - M - N
\ /
topic C - D
Merge commit (F)
would be the culprit in this scenario.
回答1:
I have discovered a solution to this problem. It was all in the letter that Linus wrote regarding reverting faulty merges: How to revert a faulty merge.
The git merge --strategy=ours topic
in our case was not intended. Even though it's a faulty merge, it can't be reverted, and having long been pushed, has the same effect of having a revert merge commit without being able to revert the revert commit.
The solution was to checkout the topic branch, run rebase --no-ff
from the first commit and then merge that branch back into master.
git checkout topic
git rebase -i --no-ff <C>
git checkout master
git merge topic
This had the effect of yielding:
fixed–topic C'–––D'––––––––––––––––––––-
/ \
master A–––B–––E–––F–––G –––> L–––M–––N–––F2
\ /
topic C–––D
To really understand this in-depth, read the last portion of the letter How to Revert a Faulty Merge using the --no-ff
rebase option to re-create the branch.
回答2:
@Highway of Life has a great answer. The one thing is that the rebased commits now look like new different commits, which in many cases may be undesirable. I wanted to merge the identical commits a second time, but git-merge
prevents this. However, I find time and again that it is always possible to get git to do what you want.
Follow Highway of Life's instructions but don't merge straight onto master:
git checkout -b fixed-topic <D> git rebase -i --no-ff <B> git checkout -b re-merged master git merge fixed-topic
This results in:
re-merged ––––––––––––––––––––------R / / fixed–topic C'–––D' / / / master A–––B–––E–––F–––G –––> L–––M–––N–––F2 \ / topic C–––D
Now the tree is set up exactly how you want—all the files show exactly the contents you desire. The one problem is that your merge commit's parents are rebased copies of your original commits, instead of actually being the original commits themselves. It's easy to fix this with git-reparent:
git reparent -p master -p <D>
This ends up with:
master A–––B–––E–––F–––G –––> L–––M–––N–––F2 \ / \ topic C–––D \ \ \ re-merged ---------------------------R
An important thing to note is that the contents of R haven't changed since the last step—only the parents.
Fast-forward master to the new merge commit:
git checkout master git merge re-merged
Finally you can clean up with
git branch -d fixed-topic re-master
Done! Now your history looks like this, with one branch merged twice:
master A–––B–––E–––F–––G –––> L–––M–––N–––F2---R
\ / /
topic C–––D----------------------------
回答3:
a merge strategy that says "keep what you have here no matter what you're merging in" by it's nature cannot be reversed. Checkout the 1st parent of the merge in a new branch, then do the merge again. Rebase --onto the rest of the commits you have on top of your original merge onto this one.
UPDATE:
In your case, if you don't care about the past, you can rebase G-N onto E and then just merge D onto this new master. The rebase will be trivial because F was an --ours merge.
来源:https://stackoverflow.com/questions/14225829/how-to-revert-a-merge-which-used-strategy-ours