Why does git revert complain about a missing -m option?
Asked Answered
D

4

300

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?

Datum answered 11/5, 2011 at 21:34 Comment(0)
G
367

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, i.e. 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

git cat-file -p [MERGE_COMMIT_ID] will show the parent branches in order. The first one listed would be -m 1, the second -m 2.

Grieco answered 11/5, 2011 at 21:48 Comment(11)
OK thanks. I found it easier just to change the two files that were affected by the merge and then commit some of my other changes too.Datum
Where can I find information whether I have to use -m1 or -m2, ...?Uzial
git cat-file -p [MERGE_COMMIT_ID] will show the parent branches in order. The first one listed would be -m 1, the second -m 2.Heartbreaking
git revert [HASH] -m 2 is telling me On branch 1.x-1.x nothing to commit, working directory clean but my commit is not reverted.Koodoo
the same is true of git revert 731a400e53381010ec617 -m2 (with no space)Koodoo
What I did to determine what number to give with -m was to simply try git revert -m 1 thecommithash and check if the diff looked right. If not, get rid of the revert (with a git reset --hard commit_before_revert) and try again with -m 2.Positively
So if I need to revert back past 10 merges (which is quite likely since git performs a merge automatically everytime I pull in changes from another developer) I have to do this for every single merge? Is this why git fans are so keen on rebasing, because revert is basically useless?Cameron
This is BY FAR the best explanation for this. This should be marked as the answerSyndicalism
what's all the "m" stuff? I dont see any "m 1" or "m 2" when I run git cat-file -p SOMECOMMIT. I see 3 lines labeled: tree, parent, parent.Ayo
"what that actually means is ambiguous" - I disagree. If I'm on branch-b and merge in some commits from branch-a, this results in modified content on branch-b, and no modification on branch-a. The only sensible thing "revert" can mean in this context is "undo the modifications made to branch-b". There's zero ambiguity.Coincide
Is there any canonical source that clearly explains what numbering system is understood by the --mainline flag? The documentation is (to me) a bit vague: "This option specifies the parent number (starting from 1) of the mainline and allows revert to reverse the change relative to the specified parent"Backstairs
S
61

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>^, e.g. 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 (i.e. <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, i.e., respectively the first and second parents of the merge commit.

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

Soften answered 11/5, 2011 at 22:20 Comment(2)
It's a mixed up, muddled up, shook up world. Except for Lola. Thanks a million for this fantastic alias.Epilate
Easy way to Add lola to your git commands: git config --global alias.lola "log --graph --decorate --pretty=oneline --abbrev-commit --all"Eucalyptol
J
10

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.

Johnjohna answered 24/10, 2014 at 12:56 Comment(3)
Possibly because it's not related to git-revert, which is what this question is about.Backache
I think this question is about the -m option, not exclusively about git merge. I.e., the reasoning behind the use of the -m option would seem to be similar for reverts and cherry-picks. If that's not true, please let us know. Since I haven't found any other questions that specifically address the cherry-pick use of it, thanks for this answer, which probably led google to help me find this question and useful, relevant discussion!Glidebomb
If I understand correctly, git has no record of which branch (y) was made on; as far as it knows, your picture is symmetric: the unnamed commit on the left branch isn't any better or worse than the one on the right (y) in any way. If that's correct, how does it decide which is 1 and which is 2?Bread
D
3

In the original question, the '-m option' of the git error was probably mistaken to denote a commit message. As explained in the other answers, use '-m n' to specify the nth parent of the merge to pick the parent you consider to be the main trunk.

Dioptometer answered 19/5, 2021 at 11:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.