Git: как вернуть слияние ветвей без перезаписи истории?
У меня две ветки: master
и opengl
. Недавно я закончил реализацию (или, по крайней мере, так думал) ветки opengl
и решил объединить ее в master
:
git checkout master
git merge opengl
git push
После этого несколько разработчиков, которые работают в ветке master
, вытащили мои изменения, и оказалось, что моя реализация противоречила некоторым их кодам. Поэтому я хотел бы вернуть операцию слияния в ветки master
, но без перезаписи истории.
Обратите внимание, что я хотел бы объединить ветвь opengl
в master
в конце концов (после исправления всех ошибок). Поэтому просто проверка старой версии master
и ее выполнение не сработают - недавно созданная фиксация отменяет мои изменения с opengl
, когда я попытаюсь объединить ее.
Спасибо.
Ответы
Ответ 1
Документация " Как вернуть ошибочное слияние", упомянутый cebewee объясняет, почему возврат git является сложным при возврате слияния.
Итак, слияние все еще будет существовать, и оно все равно будет рассматриваться как объединение двух ветвей вместе, а в будущих слияниях будет видно, что объединение происходит как последнее общее состояние - и возврат, который вернул слияние принесенный не повлияет на это вообще.
Если вы думаете о "возврате" как "отменить", тогда вы всегда будете пропустить эту часть ревертов.
Да, он отменяет данные, но нет, это не отменяет историю.
git revert
- правильное решение здесь, но оно будет иметь последствия в будущем, когда вы захотите снова объединить эту ветку.
Затем следующее слияние должно "сначала вернуть назад", а затем объединить ветвь.
Ответ 2
Изменить: Это не то, о чем попросил ОП, но я сохраню его здесь, если кто-то захочет найти решение, которое связано с переписыванием истории.
Во-первых, создайте новую ветку, если вы хотите сохранить фиксацию слияния локально, чтобы коммит не "исчез" после перемещения master
:
git branch erroneousMerge master
Если другие разработчики также совершили коммиты после ошибочного слияния, они тоже должны это сделать!
Затем reset master
, чтобы ссылаться на последнюю фиксацию перед слиянием; скажем, что он совершает e498b2...
:
git checkout e498b2
git branch -f master
Теперь вы можете нажать скорректированный master
(-f
означает, что вы хотите сделать сервер reset его ветвью master
на коммит, на который вы указали, хотя это коммит является предка того, на который он указывает в репозитории):
git push -f origin master
Теперь другие разработчики могут обновить свой master
, чтобы он соответствовал серверу (-f
означает, что они согласны с тем, что ветвь перемещена назад):
git fetch -f origin master:master
Если другие разработчики внесли изменения после ошибочного слияния (скажем, что коммит слияния abc123
, они могут использовать rebase
для перемещения изменений в исправленный master
:
git rebase --onto master abc123 oldMaster
Если вы в какой-то момент испортите и закончите с "потерями", потому что больше нет ветвей, указывающих на них, вы можете использовать git fsck --lost-found
для их восстановления.