Как отменить фиксацию слияния, которая уже была перенесена в удаленную ветку?

git revert <commit_hash> один не будет работать. -m должен быть указан, и я довольно смущен этим.

Кто-нибудь испытывал это раньше?

Ответ 1

Опция -m указывает родительский номер. Это потому, что коммит слияния имеет более одного родителя, и Git не знает автоматически, какой родитель был основной линией, и какой родитель был ветвью, которую вы хотите удалить -m erge.

Когда вы увидите коммит слияния в выводе git log, вы увидите его родителей в строке, начинающейся с Merge:

commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James <[email protected]>
Date:   Wed Aug 17 22:49:41 2011 +0100

Merge branch 'gh-pages'

Conflicts:
    README

В этой ситуации git revert 8f937c6 -m 1 вернет вам дерево, как это было в 8989ee0, а git revert -m 2 восстановит дерево, как это было в 7c6b236.

Чтобы лучше понять родительские идентификаторы, вы можете запустить:

git log 8989ee0 

а также

git log 7c6b236

Ответ 2

Вот полный пример в надежде, что он кому-то поможет:

git revert -m 1 <commit-hash> 
git commit -m "Reverting the last commit which messed the repo."
git push -u origin master

Где <commit-hash> - хеш фиксации слияния, который вы хотели бы вернуть, и, как указано в объяснении этого ответа, -m 1 указывает, что вы должны вернуться к дереву первого родителя до слияния.

Строка git commit ... по существу совершает ваши изменения, в то время как третья строка делает ваши изменения общедоступными, нажимая их на удаленную ветвь.

Ответ 3

Бен рассказал вам, как вернуть фиксацию слияния, но очень важно, что вы понимаете, что это делает "заявляет, что вы никогда не захотите, чтобы изменения дерева были внесены слиянием. В результате, более поздние слияния приведут только к изменениям дерева, введенным коммитами, которые не являются предками ранее восстановленного слияния. Это может быть или не быть тем, что вы хотите". (git -merge man page).

An сообщение о статье/списке рассылки, связанное с man-страницей, детализирует механизмы и соображения, которые задействованы. Просто убедитесь, что вы понимаете, что если вы вернете фиксацию слияния, вы не можете просто снова слить ветку и ожидать, что те же изменения вернутся.

Ответ 4

Вы можете выполнить следующие шаги, чтобы вернуть неверные фиксации или reset удаленной ветки назад, чтобы исправить состояние HEAD/.

  • проверка удаленной ветки на локальное репо.
    git checkout development
  • скопировать хеш фиксации (то есть идентификатор коммита непосредственно перед неправильной фиксацией) из журнала git git log -n5

    вывод:

    commit 7cd42475d6f95f5896b6f02e902efab0b70e8038" Объединить ветвь "неправильно-совершить" в "развитие" "
    commit f9a734f8f44b0b37ccea769b9a2fd774c0f0c012 "это неправильная фиксация "
    commit 3779ab50e72908da92d2cfcd72256d7a09f446ba "это правильная фиксация"

  • reset ветвь на хеш фиксации, скопированная на предыдущем шаге
    git reset <commit-hash> (i.e. 3779ab50e72908da92d2cfcd72256d7a09f446ba)

  • запустите git status, чтобы показать все изменения, которые были частью неправильной фиксации.
  • просто запустите git reset --hard, чтобы вернуть все эти изменения.
  • принудительно удалите локальную ветку на удаленную станцию ​​и обратите внимание, что ваша история фиксации чиста, поскольку она была до того, как она загрязнилась.
    git push -f origin development

Ответ 5

git revert -m 1 <merge-commit>

Ответ 6

Чтобы сохранить журнал в чистоте, так как ничего не произошло (с некоторыми недостатками при таком подходе (из-за push -f)):

git checkout <branch>
git reset --hard <commit-hash-before-merge>
git push -f origin HEAD:<remote-branch>

'commit-hash-before-merge' приходит из журнала (git log) после слияния.

Ответ 7

Иногда наиболее эффективным способом отката является откат и замена.

git log

Использовать 2-х хеш-хеш (полный хеш, тот, который вы хотите вернуть назад, до того, как произошла ошибка), а затем снова отбросить его.

git checkout -b newbranch <HASH>

Затем удалите старую ветку, скопируйте новую ветку на место и перезапустите оттуда.

git branch -D oldbranch
git checkout -b oldbranch newbranch

Если он был передан, а затем удалите старую ветку из всех репозиториев, перетащите ветвь redone на самую центральную и верните ее ко всем.

Ответ 8

Я нашел создание обратного патча между двумя знающими конечными точками и применение этого патча. Это предполагает, что вы создали моментальные снимки (теги) у своей основной ветки или даже резервные копии вашей основной ветки say master_bk_01012017.

Скажите, что ветвь кода, которую вы объединили в master, была mycodebranch.

  • Мастер проверки.
  • Создайте полный двоичный обратный патч между мастером и вашей резервной копией. git diff --binary master..master_bk_01012017 > ~/myrevert.patch
  • Проверьте свой патч git apply --check myrevert.patch
  • Применить патч с выпиской git am --signoff < myrevert.patch
  • Если вам понадобится снова ввести этот код после его исправления, вам нужно будет отделить возвращенный мастер и проверить его ветвь git branch mycodebranch_fix git checkout mycodebranch_fix
  • Здесь вам нужно найти SHA-ключ для возврата и вернуть обратно git revert [SHA]
  • Теперь вы можете использовать mycodebranch_fix для исправления проблем, фиксации и повторного слияния с мастером после выполнения.

Ответ 9

Правильно отмеченный ответ сработал для меня, но мне пришлось потратить некоторое время, чтобы определить, что происходит.. Поэтому я решил добавить ответ с простыми простыми шагами для случаев, подобных моему..

Допустим, у нас есть ветки A и B.. Вы слили ветвь A в ветвь B и подтолкнули ветвь B к себе, так что теперь слияние является частью этого... Но вы хотите вернуться к последнему коммиту перед слиянием.. Что делать ты сделаешь?

  1. Перейдите в корневую папку git (обычно это папка проекта) и используйте git log
  2. Вы увидите историю последних коммитов - коммиты имеют свойства commit/author/date, а слияния также имеют свойство merge - так что вы видите их так:

    commit: <commitHash> Merge: <parentHashA> <parentHashB> Author: <author> Date: <date>

  3. Используйте git log <parentHashA> и git log <parentHashB> - вы увидите истории коммитов этих родительских веток - первые коммиты в списке самые последние

  4. Возьмите <commitHash> коммита, который вы хотите, перейдите в корневую папку git и используйте git checkout -b <newBranchName> <commitHash> - это создаст новую ветку, начиная с последнего коммита, который вы выбрали перед слиянием. Вуаля, готово!

Ответ 11

Все ответы уже охватывали большинство вещей, но я добавлю свои 5 центов. Короче говоря, отменить коммит слияния довольно просто:

git revert -m 1 <commit-hash>

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

Вы можете найти более полезную информацию по этому вопросу здесь: https://itcodehub.blogspot.com/2019/06/how-to-revert-merge-in-git.html

Ответ 12

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

  1. Сначала проверьте git log чтобы найти идентификатор фиксации слияния. Вы также найдете несколько родительских идентификаторов, связанных с объединением (см. Изображение ниже).

enter image description here

Запишите идентификатор фиксации слияния, показанный желтым цветом. Родительские идентификаторы - это те, которые записаны в следующей строке как Merge: parent1 parent2. Сейчас...

Короткий рассказ:

  1. Переключитесь на ветку, на которой было произведено слияние. Затем просто выполните команду git revert <merge commit id> -m 1 которая откроет консоль vi для ввода сообщения фиксации. Написать, сохранить, выйти, готово!

Длинная история:

  1. Переключитесь на ветку, на которой было произведено слияние. В моем случае это test ветка, и я пытаюсь удалить из нее ветку feature/analytics-v3.

  2. git revert - это команда, которая отменяет любой коммит. Но при отмене коммита merge есть неприятный трюк. Вам необходимо ввести флаг -m иначе он потерпит неудачу. С этого parent1 вам нужно решить, хотите ли вы вернуть свою ветку и сделать так, чтобы она выглядела точно так, как это было на parent1 или parent2 помощью:

git revert <merge commit id> -m 1 (возвращается к parent2)

git revert <merge commit id> -m 2 (возвращается к parent1)

Вы можете git войти эти родители, чтобы выяснить, какой путь вы хотите пойти и что корень всей путаницы.

Ответ 13

Как отметил Райан, git revert может затруднить слияние в будущем, поэтому git revert может быть не таким, каким вы хотите. Я обнаружил, что использование команды git reset --hard <commit-hash-prior-to-merge> более полезно здесь.

Как только вы выполните жесткую часть reset, вы можете принудительно нажать на удаленную ветвь, т.е. git push -f <remote-name> <remote-branch-name>, где <remote-name> часто называют origin. С этого момента вы можете повторно объединить, если хотите.