How to revert a merge commit that's already pushed to remote branch?

后端 未结 17 1643
无人及你
无人及你 2020-11-22 07:04

git revert alone won\'t work. -m must be specified, and I\'m pretty confused about it.

Anyone experienced this before?<

相关标签:
17条回答
  • 2020-11-22 07:59

    git doc about git revert -m provide a link exactly explain this: https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt

    0 讨论(0)
  • 2020-11-22 08:01

    As Ryan mentioned, git revert could make merging difficult down the road, so git revert may not be what you want. I found that using the git reset --hard <commit-hash-prior-to-merge> command to be more useful here.

    Once you have done the hard reset part, you can then force push to the remote branch, i.e. git push -f <remote-name> <remote-branch-name>, where <remote-name> is often named origin. From that point you can re-merge if you'd like.

    0 讨论(0)
  • 2020-11-22 08:02

    I found good explanation for How To Revert The Merge from this link and I copy pasted the explanation below and it would be helpful just in case if below link doesn't work.

    How to revert a faulty merge Alan(alan@clueserver.org) said:

    I have a master branch. We have a branch off of that that some developers are doing work on. They claim it is ready. We merge it into the master branch. It breaks something so we revert the merge. They make changes to the code. they get it to a point where they say it is ok and we merge again. When examined, we find that code changes made before the revert are not in the master branch, but code changes after are in the master branch. and asked for help recovering from this situation.

    The history immediately after the "revert of the merge" would look like this:

    ---o---o---o---M---x---x---W
                  /
          ---A---B
    

    where A and B are on the side development that was not so good, M is the merge that brings these premature changes into the mainline, x are changes unrelated to what the side branch did and already made on the mainline, and W is the "revert of the merge M" (doesn’t W look M upside down?). IOW, "diff W^..W" is similar to "diff -R M^..M".

    Such a "revert" of a merge can be made with:

    $ git revert -m 1 M After the developers of the side branch fix their mistakes, the history may look like this:

    ---o---o---o---M---x---x---W---x
                  /
          ---A---B-------------------C---D
    

    where C and D are to fix what was broken in A and B, and you may already have some other changes on the mainline after W.

    If you merge the updated side branch (with D at its tip), none of the changes made in A or B will be in the result, because they were reverted by W. That is what Alan saw.

    Linus explains the situation:

    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. In such a situation, you would want to first revert the previous revert, which would make the history look like this:

    ---o---o---o---M---x---x---W---x---Y
                  /
          ---A---B-------------------C---D
    

    where Y is the revert of W. Such a "revert of the revert" can be done with:

    $ git revert W This history would (ignoring possible conflicts between what W and W..Y changed) be equivalent to not having W or Y at all in the history:

    ---o---o---o---M---x---x-------x----
                  /
          ---A---B-------------------C---D
    

    and merging the side branch again will not have conflict arising from an earlier revert and revert of the revert.

    ---o---o---o---M---x---x-------x-------*
                  /                       /
          ---A---B-------------------C---D
    

    Of course the changes made in C and D still can conflict with what was done by any of the x, but that is just a normal merge conflict.

    0 讨论(0)
  • 2020-11-22 08:03

    Ben has told you how to revert a merge commit, but it's very important you realize that in doing so

    "...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. This may or may not be what you want." (git-merge man page).

    An article/mailing list message linked from the man page details the mechanisms and considerations that are involved. Just make sure you understand that if you revert the merge commit, you can't just merge the branch again later and expect the same changes to come back.

    0 讨论(0)
  • 2020-11-22 08:05

    If you want to revert a merge commit, here is what you have to do.

    1. First, check the git log to find your merge commit's id. You'll also find multiple parent ids associated with the merge (see image below).

    Note down the merge commit id shown in yellow. The parent IDs are the ones written in the next line as Merge: parent1 parent2. Now...

    Short Story:

    1. Switch to branch on which the merge was made. Then Just do the git revert <merge commit id> -m 1 which will open a vi console for entering commit message. Write, save, exit, done!

    Long story:

    1. Switch to branch on which the merge was made. In my case, it is the test branch and I'm trying to remove the feature/analytics-v3 branch from it.

    2. git revert is the command which reverts any commit. But there is a nasty trick when reverting a merge commit. You need to enter the -m flag otherwise it will fail. From here on, you need to decide whether you want to revert your branch and make it look like exactly it was on parent1 or parent2 via:

    git revert <merge commit id> -m 1 (reverts to parent2)

    git revert <merge commit id> -m 2 (reverts to parent1)

    You can git log these parents to figure out which way you want to go and that's the root of all the confusion.

    0 讨论(0)
提交回复
热议问题