Почему git revert жалуется на отсутствие опции -m?

Итак, я работаю над проектом с другими людьми, и над ним работают несколько форков github. Кто-то только что исправил проблему, и я слился с его вилкой, но потом понял, что могу найти лучшее решение. Я хочу отменить только что сделанную фиксацию. Я пытался сделать это с помощью git revert HEAD, но это дало мне такую ​​ошибку:

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

Что это обозначает? Когда я слился и зафиксировал, я использовал параметр -m, чтобы сказать «Объединено с ‹username>».

Что я здесь делаю не так?


person icnhzabot    schedule 11.05.2011    source источник


Ответы (4)


По умолчанию git revert отказывается отменить фиксацию слияния, поскольку на самом деле это неоднозначно. Я предполагаю, что ваш HEAD на самом деле является фиксацией слияния.

Если вы хотите отменить фиксацию слияния, вы должны указать, какой родительский элемент слияния вы хотите считать основным стволом, то есть к чему вы хотите вернуться.

Часто это будет родитель номер один, например, если вы были на master и сделали git merge unwanted, а затем решили отменить слияние unwanted. Первый родитель будет вашей веткой перед объединением master, а второй родитель будет вершиной unwanted.

В этом случае вы можете:

git revert -m 1 HEAD

git cat-file -p [MERGE_COMMIT_ID] покажет родительские ветки по порядку. Первым в списке будет -m 1, вторым -m 2.

person CB Bailey    schedule 11.05.2011
comment
Хорошо спасибо. Мне было проще просто изменить два файла, на которые повлияло слияние, а затем зафиксировать некоторые из моих других изменений. - person icnhzabot; 12.05.2011
comment
Где я могу найти информацию, нужно ли мне использовать -m1 или -m2, ...? - person Patrick Cornelissen; 18.07.2016
comment
git cat-file -p [MERGE_COMMIT_ID] покажет родительские ветки по порядку. Первым в списке будет -m 1, вторым -m 2. - person nostromo; 12.10.2016
comment
git revert [HASH] -m 2 говорит мне, что в ветке 1.x-1.x нечего фиксировать, рабочий каталог чист, но моя фиксация не отменена. - person jenlampton; 29.11.2016
comment
то же самое верно и для git revert 731a400e53381010ec617 -m2 (без пробелов) - person jenlampton; 29.11.2016
comment
Что я сделал, чтобы определить, какое число дать с -m, так это просто попробовать git revert -m 1 thecommithash и проверить, правильно ли выглядит разница. В противном случае избавьтесь от возврата (с помощью git reset --hard commit_before_revert) и повторите попытку с -m 2. - person Henrik N; 06.03.2017
comment
Итак, если мне нужно вернуться назад после 10 слияний (что вполне вероятно, поскольку git выполняет слияние автоматически каждый раз, когда я извлекаю изменения от другого разработчика), я должен делать это для каждого слияния? Не поэтому ли фанаты git так стремятся к ребазированию, ведь откат в принципе бесполезен? - person Neutrino; 17.09.2017
comment
Это НАМНОГО лучшее объяснение этому. Это должно быть отмечено как ответ - person dVyper; 26.04.2018

Допустим, другой парень создал bar поверх foo, но вы тем временем создали baz, а затем слились, давая историю

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

Примечание. git lola - нестандартный, но полезный псевдоним.

Нет кубиков с git revert:

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

Чарльз Бейли, как обычно, дал отличный ответ. Использование git revert, как в

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

эффективно удаляет bar и создает историю

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

Но я подозреваю, что вы хотите выбросить фиксацию слияния:

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

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

Как описано в git rev-parse manual

<rev>^, например HEAD ^, v1.5.1^0
Суффикс ^ параметра редакции означает первого родителя этого объекта фиксации. ^<n> означает n -го родителя (т.е. <rev>^ эквивалентно <rev>^1). В качестве специального правила <rev>^0 означает саму фиксацию и используется, когда <rev> - это имя объекта объекта тега, который ссылается на объект фиксации.

поэтому перед вызовом git reset, HEAD^ (или HEAD^1) было b7e7176, а HEAD^2 было c7256de, т.е., соответственно первым и вторым родителями коммита слияния.

Будьте осторожны с git reset --hard, потому что это может испортить работу.

person Greg Bacon    schedule 11.05.2011
comment
Это запутанный, запутанный, потрясенный мир. Кроме Лолы. Спасибо за этот фантастический псевдоним. - person Barney; 28.01.2016
comment
Простой способ добавить lola в команды git: git config --global alias.lola "log --graph --decorate --pretty=oneline --abbrev-commit --all" - person D. Gibbs; 28.04.2020

У меня была эта проблема, решение заключалось в том, чтобы посмотреть на график фиксации (используя gitk) и увидеть, что у меня было следующее:

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

Теперь я понимаю, что хочу сделать

git cherry-pick -m 2 mycommitsha

Это связано с тем, что -m 1 будет объединяться на основе общего родителя, тогда как -m 2 объединяется на основе ветки y, это та, которую я хочу выбрать.

person shmish111    schedule 24.10.2014
comment
Возможно, потому, что это не связано с git-revert, о чем идет речь. - person pnomolos; 09.05.2016
comment
Я думаю, что этот вопрос касается варианта -m, а не исключительно git merge. То есть, аргументы в пользу использования опции -m кажутся схожими для возврата и выбора вишни. Если это не так, дайте нам знать. Поскольку я не нашел никаких других вопросов, которые бы конкретно касались его использования в качестве вишенки, спасибо за этот ответ, который, вероятно, побудил Google помочь мне найти этот вопрос и полезное, актуальное обсуждение! - person nealmcb; 30.11.2017
comment
Если я правильно понимаю, в git нет записи о том, какая ветвь (y) была создана; насколько ему известно, ваша картина симметрична: безымянный коммит в левой ветке ни в коем случае не лучше и не хуже, чем тот, что справа (y). Если это верно, как он решает, где 1, а где 2? - person Don Hatch; 29.09.2020

В исходном вопросе опция -m ошибки git, вероятно, ошибочно указывала на сообщение о фиксации. Как объясняется в других ответах, используйте '-m n', чтобы указать n-й родительский элемент слияния, чтобы выбрать родительский элемент, который вы считаете основным стволом.

person Maarten Folkers    schedule 19.05.2021