Отменить слияние после нажатия
Шаги, которые я выполнил:
У меня есть две ветви branch1 и branch2,
$git branch --Initial state
$branch1
$git checkout branch2
$git pull origin branch1 --Step1
Я разрешил конфликты и сделал
$git commit -m "Merge resolved"
затем
$git checkout branch1
$git merge branch2
$git push origin branch1
Теперь я понял, что, находясь на шаге 1, автоматическое объединение удалило некоторый код, и код изменения был перенесен, теперь я хочу вернуться в исходное состояние, чтобы отменить любые изменения. Ищете немедленную помощь?
6 ответов
Вы можете отменить слияние, следуя официальному руководству, однако это оставляет Git ошибочным убеждением, что слитые коммиты все еще находятся в целевой ветви.
В основном вы должны:
git revert -m 1 (Commit id of the merge commit)
Попробуйте использовать git reflog <branch>
выяснить, где была ваша ветка до слияния и git reset --hard <commit number>
восстановить старую ревизию.
Reflog покажет вам старые состояния ветки, так что вы можете вернуть его в любой набор изменений, который вам нравится.
Убедитесь, что вы находитесь в правильной ветке при использовании git reset
Чтобы изменить историю удаленного хранилища, вы можете сделать git push -f
Однако это не рекомендуется, потому что кто-то может уже загрузить изменения, сделанные вами.
Первый вариант - это использование git revert
,
git revert -m 1 [sha-commit-before-merge]
git revert
отменит изменения, но сохранит историю. Поэтому вы не сможете продолжать работать в той же ветке, так как больше не видите фактической разницы между объединенной ветвью и вашей веткой компонентов. Используйте следующий способ, чтобы удалить историю. Делайте это очень осторожно, если и только если вы единственный, кто вносит изменения в ветку в данный момент.
git reset --hard [sha-commit-before-merge]
git push [origin] [branch] --force
Дополнительные пояснения к данному ответуgit revert -m 1 <merge commit id>
с графическим представлением и примером, шаг за шагом.
Отменить фиксацию слияния не так просто, как в случаеgit revert <commit-hash>
, так как Git запутывается, оглядываясь на коммит слияния из-за его двух родительских коммитов. Чтобы указать желаемого родителя, используется-m
флаг. Поскольку git не может определить, какой родитель является основной линией, а какая — ветвью, которую нужно автоматически разъединить, это необходимо указать.
Филиал был объединен с , создавMerge Commit
, . было двое родителей и .
Нужно вернутьсяC6
и верните репозиторий в его состояние в . Поэтому он должен указать, какой родитель использовать для команды возврата.
Для этого проверьте ( здесь представлен фактический хэш коммита с кодовыми именами из графика )
> git log commit C6 Merge: C4 C5 Author: Mozz <mozz@example.com> Date: Wed Feb 29 23:59:59 2020 +0100 Merge branch 'iss53' to master ...
Из вывода запишите родительские идентификаторы, которые поставляются с
Merge: - -
. Он будет в форматеMerge: parent1 parent2
, здесьMerge: C4 C5
.The
C4
commit находится в ветке, и нам нужно вернуться к тому, что является родителем 1 и требуется здесь (используйтеgit log C4
для проверки предыдущих коммитов для подтверждения родительской ветки).Переключитесь на ветку, на которой было выполнено слияние (это
master
ветвь здесь, и мы стремимся удалитьiss53
ответвление от него)Верните git с помощью
-m 1
флаг.# To revert to C4 in master branch git revert C6 -m 1 # C6 - is the merge commit hash
В некоторых других случаях при необходимости вернитесь кC5
,
# revert to C5 in iss53 branch
git revert C6 -m 2
# General
git revert <merge commit id> -m 1 (reverts to parent1)
git revert <merge commit id> -m 2 (reverts to parent2)
# remember to check and verify the parent1 and parent2 with git log command.
Практический пример
Создал новую ветку в существующем проекте, который имеет только ветку. График фиксации теперь выглядит так.
(Для графического представления коммитов используйте
—graph
с [ SO ans ref] ИЛИ это более интерактивное расширение кода VS - git graph)
Теперь я добавил несколько новых файлов, изменил существующие файлы и создал отдельные коммиты в каждой ветке, а затем отправил их в источник. Теперь график выглядит так:
Затем создал запрос на извлечение из GitHub и объединил ветку с .
Я хочу отменить фиксацию слияния и вернуться к последней фиксации в ветке, которая
Обратите внимание, что коммит слияния -2ec06d9
теперь имеет двух родителей - (вmain
) и15bde47
(вrevert-test
), проверкаgit log
сейчас,
> git log
commit 2ec06d9d315a3f7919ffe4ad2c2d7cec8c8f9aa3 (HEAD -> main, origin/main, origin/HEAD)
Merge: 12a7327 15bde47
Author: Akshay <63786863+akshay@users.noreply.github.com>
Date: Sun Feb 5 00:41:13 2023 +0530
Merge pull request #1 from Akshay/revert-test
Revert test
Чтобы отменить фиксацию слияния и вернуться к12a7327
нужно сделать,
# To the First parent
git revert 2ec06d9 -m 1
Теперь в редакторе появится сообщение фиксации, в котором указаны детали, проверка и проверка.
Таким образом, создается фиксация Revert, которая выполняет обратные изменения коммита слияния.
Наконец, внесите изменения. Теперь изменения фиксации слияния исчезли, и журнал будет выглядеть так:
В моем случае я объединил свою ветку (скажем: my-branch) с другой функциональной веткой (feature-branch), но не с master. Итак, история моей ветки была такой:
my-branch (before merge)
---master----m1----m2----m3---m4
После слияния с другим feature-branch
который имел коммиты f1, f2
поверх мастера получилось так:
my-branch (after merge)
---master----m1----m2----f1----f2----m3---m4----mergecommit
Это могло произойти из-за того, что во время работы над моей веткой я выполнил слияние из master после 2 коммитов, или одна из 2 веток могла не обновляться с master. Так что в этом случаеgit revert -m 1
не работал, так как оставил те f1
а также f2
совершает между ними.
Решение было простым, которое будет работать в обычных сценариях, когда у нас нет промежуточных коммитов:
git rebase -i HEAD~6
Вместо 6 используйте соответствующее число в зависимости от того, сколько прошлых коммитов вы хотите изменить. Теперь редактор Vim открыт, просто отметьте нежелательные коммиты какdrop
и то же самое и прекратить использование :wq
проверить журнал:
git log --oneline
принудительный толчок
git push -f
Теперь удаленная ветка должна быть в предыдущем состоянии.
Как упоминалось в другом ответе, основная проблема с выполнением
git revert
при слиянии заключается в том, что git по-прежнему считает, что все предыдущие коммиты были объединены (он только меняет код). Если вы попытаетесь объединить эту ветку позже, вы обнаружите, что эти предыдущие коммиты отсутствуют.
Лучший способ (очевидно, после консультации с вашей командой, чтобы они не продолжали работать над проблемной веткой) - это
git reset
к более ранней фиксации. Это не обязательно должен быть полный сброс, так как он касается только того, что делать с вашими текущими рабочими изменениями, так что эта часть зависит от вас.
Вы также можете создать временную ветку из предыдущего коммита, если хотите сначала внести в нее изменения, прежде чем выполнять сброс. В этом случае вы сбросите коммит на временную ветку.
Вы не сможете нажать, не вытягивая из своего восходящего потока, но, очевидно, вы не хотите вытягивать изменения, которые пытаетесь отменить. Таким образом, вам нужно выполнить принудительное нажатие (или принудительное нажатие с арендой, чтобы остановить, если какие-либо изменения были внесены в промежутке).
Боковое примечание. Как поклонник VS Code и Git Graph, я считаю, что принудительное нажатие легко сделать, щелкнув правой кнопкой мыши имя тега локальной ветки и выбрав «Отправить ветку...», выбрав «Принудительно» или «Принудительно с арендой», оставив флажок Set Upstream установлен.