Откат Git слияния

227
develop branch
--> dashboard (working branch)

Я использую, git merge --no-ff developчтобы объединить любые восходящие изменения в приборной панели

git log:

commit 88113a64a21bf8a51409ee2a1321442fd08db705
Merge: 981bc20 888a557
Author: XXXX <>
Date:   Mon Jul 30 08:16:46 2012 -0500

    Merge branch 'develop' into dashboard

commit 888a5572428a372f15a52106b8d74ff910493f01
Author: root <root@magneto.giveforward.com>
Date:   Sun Jul 29 10:49:21 2012 -0500

    fixed end date edit display to have leading 0

commit 167ad941726c876349bfa445873bdcd475eb8cd8
Author: XXXX <>
Date:   Sun Jul 29 09:13:24 2012 -0500

В слиянии было около 50+ коммитов, и мне интересно, как просто отменить слияние, чтобы панель инструментов вернулась к состоянию предварительного слияния

Во-вторых, если я не выполняю слияние --no-ff, я не получаю коммит ' ветвь слияния' превращается 'в панель инструментов ' .. Как бы я откатил это слияние назад?

cgmckeever
источник
3
Возможный дубликат отмены слияния Git? ,

Ответы:

321

Отмена фиксации слияния была подробно рассмотрена в других вопросах. Когда вы выполняете ускоренное слияние, второе, которое вы описываете, вы можете использовать git resetдля возврата в предыдущее состояние:

git reset --hard <commit_before_merge>

Вы можете найти <commit_before_merge>с git reflog, git logили, если вы чувствуете смятение (и больше ничего не сделали):git reset --hard HEAD@{1}

Кристофер
источник
6
спасибо за быстрый ответ .. глядя на git log, коммит до слияния 50+ коммитов возвращается, так как разработка git merge фактически вставляет все остальные коммиты. Я думаю, что я не получаю, если я не знаю, что / где было это слияние - как мне его найти? Вы упоминаете о поиске commit_before_merge .. Я думаю, я не понимаю эту часть
cgmckeever
4
Похоже, с git reflog выглядит так, как будто хорошо суммирует последние заголовки и позволяет мне узнать, куда мне нужно выполнить сброс. В журнале git слишком много гранулярности, чтобы определить место для сброса. Спасибо
cgmckeever
1
Да, reflogспасатель. HEAD@{1}просто описывает второе самое последнее состояние HEAD, или более технически: «Ссылка, за которой следует суффикс @ с порядковым номером, заключенным в пару скобок (например, {1}, {15}), указывает n-е предшествующее значение этого исх «.
Кристофер
4
Как насчет подталкивания к удаленному? Я не вижу, как это будет работать.
Антон Савельев
2
Это безнадежно. Уничтожает все коммиты после слияния.
aaa90210
152

Отсюда:

http://www.christianengvall.se/undo-pushed-merge-git/

git revert -m 1 <merge commit hash>

Git revert добавляет новый коммит, который откатывает указанный коммит.

Использование -m 1 говорит о том, что это слияние, и мы хотим откатиться до родительского коммита в главной ветви. Вы должны использовать -m 2, чтобы указать ветку разработки.

sturrockad
источник
30
Обратите внимание, что вы не можете повторно объединить ветвь после этого, как сказано в документации: «Обращение коммита слияния объявляет, что вы никогда не захотите изменений дерева, внесенных слиянием. В результате, последующие слияния будут только вносить изменения дерева коммитами, которые не являются предками ранее отмененного слияния. Это может или не может быть тем, что вы хотите. "
Далибор Карлович
23
@ DaliborKarlović Это утверждение немного резкое. Вы можете определенно вернуть эти изменения позже, трюк состоит в том, чтобы отменить возвращенный коммит. Более подробная информация здесь, в разделе «Возврат к возврату»
Hilikus
3
К сожалению, hereссылка в комментарии @Hilikus больше не действительна. Сайт утверждает, что контент был перенесен в книгу ( git-scm.com/book/en/v2 ), но если это так, то найти его там нетривиально.
Джесси Чисхолм
@ DaliborKarlović - это случай с ответом выше от @Christopher?
Джеймс Б.
3
Содержимое для
SEK
28

Просто сбросьте коммит слияния с git reset --hard HEAD^.

Если вы используете --no-ff, git всегда создает слияние, даже если вы ничего не делаете между ними. Без --no-ff git просто сделает перемотку вперед, что означает, что для ваших веток HEAD будет установлено значение HEAD объединенной ветки. Чтобы решить эту проблему, найдите идентификатор фиксации, к которому вы хотите вернуться и git reset --hard $COMMITID.

Нико Эрфурт
источник
1
Хорошее решение, если вы не знаете коммит до слияния.
iglesiasedd
Работал для меня, поскольку я не знаю, передайте идентификатор. + 1
Анант Сингх --- Жив, чтобы умереть
если нежелательное слияние уже было зафиксировано на удаленном компьютере, я использовал git push -f для обновления удаленной ветви после возврата.
zumek
16
git revert -m 1 88113a64a21bf8a51409ee2a1321442fd08db705

Но могут иметь неожиданные побочные эффекты. См --mainline parent-numberвариант в git-scm.com/docs/git-revert

Возможно, грубым, но эффективным способом было бы проверить левого родителя этого коммита, сделать копию всех файлов, HEADснова оформить заказ и заменить все содержимое старыми файлами. Затем git скажет вам, что откатывается, и вы создадите свой собственный возвратный коммит :)!

Хорхе Орпинель
источник
1
+1, потому что этот ответ не связывается с историей, как сброс (действительно важно, если вы уже перешли на удаленный доступ). Но каких неожиданных побочных эффектов мне следует ожидать?
Pedromanoel
3
Это побочный эффект, который вы упомянули? Reverting a merge commit 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.
Pedromanoel
1
Вы говорите, git resetчто это решение, но также упоминаете, что оно может иметь неожиданные побочные эффекты. Тем не менее, эта ссылка от git revert, а не git reset:)
Марк
2
Пожалуйста, обратите внимание, git reset не имеет флага -m. Также обратите внимание, что @JorgeOrpinel ссылается на документы git-revert, а не git-reset. Я думаю, что он хотел сказать git revertнетgit reset
Девин Глисон Ламберт
Как избежать Mainline было указано, но фиксация 1234xyz не является ошибкой слияния .
Achal
0

Если вы слили ветвь, то отменили слияние, используя запрос на извлечение, и объединили этот запрос на откат для возврата.

Самым простым способом, который я чувствовал, было:

  1. Возьмите новую ветку от Develop / Master (где вы слились)
  2. Отменить «возврат», используя git revert -m 1 xxxxxx(если возврат был объединен с использованием ветви) или используя, git revert xxxxxxесли это был простой возврат
  3. Новая ветвь теперь должна иметь изменения, которые вы хотите снова объединить.
  4. Внесите изменения или объедините эту ветку для разработки / master
Рохин Так
источник