Полное руководство по отмене слияний в Git


Как отменить неотправленное слияние

Если вы выполнили слияние, но ещё не оттолкнули его, отменить слияние очень просто.

Используйте команду git reset, чтобы вернуться к ревизии до слияния, тем самым фактически отменив его.

$ git reset --hard <commit-hash-before-merge>
Вход в полноэкранный режим Выход из полноэкранного режима

Если у вас под рукой нет хэша коммита перед слиянием, вы можете воспользоваться командой git log, чтобы узнать его, или использовать следующий вариант команды reset:

$ git reset --hard HEAD~1
Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, используя HEAD~1, вы говорите git’у вернуться к коммиту перед текущей ревизией HEAD, который должен быть коммитом перед слиянием.

Примечание: В обоих случаях нам нужно использовать опцию --hard. Это означает, что все локальные незафиксированные изменения будут отброшены — если у вас есть ценные незафиксированные изменения, обязательно используйте git stash перед этим.

После выполнения вышеуказанного git reset вы заметите, что все изменения после слияния будут отменены, и вы сможете продолжить работу в обычном режиме.

Как отменить сдвинутое слияние

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

Что такое родительский коммит?

У каждого коммита есть родительский коммит. Когда вы git commit, текущий коммит становится родительским для нового коммита, который вы создаёте.

Чтобы просмотреть родительский коммит, используйте git show --pretty=raw <commit-hash>.

Что такое коммит слияния?

Когда ветвь с именем feature объединяется с ветвью master, создаётся новый «merge commit» на ветви master. Коммит слияния такой же, как и обычный коммит, за исключением того, что у него есть 2 родителя. В данном случае двумя родителями коммита слияния будут предыдущая голова master и голова feature.

При запуске git show новый коммит отобразит обоих родителей:

$ git show

commit ae2058cf5cafe807af44114d15bac65fc4efd714 (HEAD -> master)
Merge: bf75d61d8f1 12d62bfa0e0
Войти в полноэкранный режим Выйти из полноэкранного режима

Как работает git revert?

git revert <commit-hash>
Войти в полноэкранный режим Выйти из полноэкранного режима

Команда revert в git принимает хэш коммита и сравнивает изменения с родительским. Вычисляется дельта или разница, и её отрицание применяется как новый коммит.

Что происходит, если мы хотим вернуть коммит слияния? Коммит слияния имеет двух родителей, и git не знает автоматически, кто из родителей был основной веткой, а кто — веткой, которую вы хотите отменить.

Отмена коммита слияния

$ git revert -m 1 <merge-commit-hash>
Войдите в полноэкранный режим Выход из полноэкранного режима

Давайте рассмотрим подробнее, что делает эта команда:

  • Опция -m 1 говорит git’у, что мы хотим сохранить родительскую сторону слияния (то есть ветвь, в которую мы слились).
  • Наконец, не забудьте указать хэш фактического коммита слияния.

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

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

commit ae2058cf5cafe807af44114d15bac65fc4efd714
Merge: bf75d61d8f1 12d62bfa0e0
Author: Michael Seymour <michael@example.com>
Date:   Sun May 08 13:52:29 2022 +0100

Merge branch 'my-branch'
Вход в полноэкранный режим Выйти из полноэкранного режима

В этой ситуации git revert ae2058cf5ca -m 1 вернёт вам дерево, каким оно было в bf75d61d8f1, а git revert -m 2 восстановит дерево, каким оно было в 12d62bfa0e0.

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

Почему мы не можем использовать git reset в этот раз?

git revert обеспечит создание нового коммита для отмены последствий этого нежелательного слияния. Это противоположно git reset, где мы фактически «удаляем» коммит из истории. Следовательно, git revert является лучшим решением в случаях, когда вы уже переместили репозиторий на удалённое место, так как изменение истории удалённого репозитория может вызвать проблемы у других разработчиков, использующих этот репозиторий.

Ссылки

  • https://www.git-tower.com/learn/git/faq/undo-git-merge
  • https://stackoverflow.com/q/7099833
  • https://levelup.gitconnected.com/reverting-a-merge-commit-7de2e9114c7d
  • https://git-school.github.io/visualizing-git/#free

Оцените статью
Procodings.ru
Добавить комментарий