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

185

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

Фатально: Commit <SHA1> - это слияние, но опция -m не указана.

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

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

icnhzabot
источник

Ответы:

217

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

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

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

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

git revert -m 1 HEAD
CB Bailey
источник
4
Хорошо, спасибо. Мне было проще просто изменить два файла, которые были затронуты слиянием, а затем зафиксировать некоторые другие мои изменения тоже.
icnhzabot
43
Где я могу найти информацию, должен ли я использовать -m1 или -m2, ...?
Патрик Корнелиссен
34
git cat-file -p [MERGE_COMMIT_ID]покажет родительские ветви в порядке. Первый в списке будет -m 1, второй -m 2.
Ностромо
2
git revert [HASH] -m 2В ветке 1.x-1.x мне ничего не говорится, рабочий каталог чист, но моя фиксация не отменена.
Дженламптон
3
Поэтому, если мне нужно отменить последние 10 слияний (что вполне вероятно, поскольку git выполняет слияние автоматически каждый раз, когда я получаю изменения от другого разработчика), я должен делать это для каждого слияния? Вот почему поклонники git так стремятся к перебазированию, потому что возврат в принципе бесполезен?
Нейтрино
46

Скажем, другой парень создал панель поверх foo, но вы тем временем создали базу, а затем слились, дав историю

$ git lola
* 2582152 (HEAD, master) Слияние веток 'otherguy'
| \  
| * c7256de (другой) бар
* | b7e7176 баз
| /  
* 9968f79 foo

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

Нет кости с git revert:

$ git revert HEAD
фатальный: совершить 2582152 ... слияние, но опция -m не указана.

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

$ git revert --no-edit -m 1 HEAD
[master e900aad] Вернуть "Объединить ветку 'otherguy'"
 0 файлов изменено, 0 вставок (+), 0 удалений (-)
 режим удаления 100644 бар

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

$ git lola
* e900aad (HEAD, master) Возврат "Объединить ветку 'otherguy'"
* 2582152 Объединить ветку 'otherguy'
| \  
| * c7256de (другой) бар
* | b7e7176 баз
| /  
* 9968f79 foo

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

$ git reset --hard HEAD ^
ГОЛОВА сейчас на b7e7176 баз

$ git lola
* b7e7176 (HEAD, master) баз
| * c7256de (другой) бар
| /  
* 9968f79 foo

Как указано в git rev-parseруководстве

<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потому что это может разрушить работу.

Грег Бэкон
источник
3
Это запутанный, запутанный, потрясенный мир. За исключением Лолы. Спасибо миллион за этот фантастический псевдоним.
Барни
Простой способ добавить lolaв свои команды git:git config --global alias.lola "log --graph --decorate --pretty=oneline --abbrev-commit --all"
D. Gibbs
8

У меня была эта проблема, решение было посмотреть на график фиксации (используя 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, это то, что я хочу выбрать из вишни.

shmish111
источник
1
Возможно, потому что это не связано git-revert, о чем этот вопрос.
pnomolos
1
Я думаю, что этот вопрос о -mварианте, а не только о git merge. То есть обоснование использования -mопции, похоже, было бы схожим для возвратов и черриков. Если это не так, пожалуйста, дайте нам знать. Поскольку я не нашел никаких других вопросов, которые конкретно касались бы его использования, спасибо за этот ответ, который, вероятно, помог Google найти этот вопрос и полезную, актуальную дискуссию!
nealmcb