Why does git revert complain about a missing

So I'm working on a project with other people, and there's multiple github forks being worked on. Someone just made a fix for a problem and I merged with his fork, but then I realized that I could find a better solution. I want to revert the commit I just made. I tried doing this with git revert HEAD but it gave me this error:

fatal: Commit <SHA1> is a merge but no -m option was given.

What does that mean? When I merged and committed, I did use the -m option to say "Merged with <username>".

What am I doing wrong here?


By default git revert refuses to revert a merge commit as what that actually means is ambiguous. I presume that your HEAD is in fact a merge commit.

If you want to revert the merge commit, you have to specify which parent of the merge you want to consider to be the main trunk, ie what you want to revert to.

Often this will be parent number one, for example if you were on master and did git merge unwanted and then decided to revert the merge of unwanted . The first parent would be your pre-merge master branch and the second parent would be the tip of unwanted .

In this case you could do:

git revert -m 1 HEAD

Say the other guy created bar on top of foo, but you created baz in the meantime and then merged, giving a history of

$ git lola
*   2582152 (HEAD, master) Merge branch 'otherguy'
|  
| * c7256de (otherguy) bar
* | b7e7176 baz
|/  
* 9968f79 foo

Note: git lola is a non-standard but useful alias.

No dice with git revert :

$ git revert HEAD
fatal: Commit 2582152... is a merge but no -m option was given.

Charles Bailey gave an excellent answer as usual. Using git revert as in

$ git revert --no-edit -m 1 HEAD
[master e900aad] Revert "Merge branch 'otherguy'"
 0 files changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 bar

effectively deletes bar and produces a history of

$ git lola
* e900aad (HEAD, master) Revert "Merge branch 'otherguy'"
*   2582152 Merge branch 'otherguy'
|  
| * c7256de (otherguy) bar
* | b7e7176 baz
|/  
* 9968f79 foo

But I suspect you want to throw away the merge commit:

$ git reset --hard HEAD^
HEAD is now at b7e7176 baz

$ git lola
* b7e7176 (HEAD, master) baz
| * c7256de (otherguy) bar
|/  
* 9968f79 foo

As documented in the git rev-parse manual

<rev>^ , eg HEAD^, v1.5.1^0
A suffix ^ to a revision parameter means the first parent of that commit object. ^<n> means the n-th parent (ie <rev>^ is equivalent to <rev>^1 ). As a special rule, <rev>^0 means the commit itself and is used when <rev> is the object name of a tag object that refers to a commit object.

so before invoking git reset , HEAD^ (or HEAD^1 ) was b7e7176 and HEAD^2 was c7256de, ie, respectively the first and second parents of the merge commit.

Be careful with git reset --hard because it can destroy work.


I had this problem, the solution was to look at the commit graph (using gitk) and see that I had the following:

*   commit I want to cherry-pick (x)
|  
| * branch I want to cherry-pick to (y)
* | 
|/  
* common parent (x)

I understand now that I want to do

git cherry-pick -m 2 mycommitsha

This is because -m 1 would merge based on the common parent where as -m 2 merges based on branch y, that is the one I want to cherry-pick to.

链接地址: http://www.djcxy.com/p/408.html

上一篇: 签出旧的提交并使其成为新的提交

下一篇: 为什么git回复抱怨失踪