Удалите слияние, сохраняя текущие изменения
У нас была небольшая проблема в нашей команде. Один разработчик должен был внести некоторые изменения в нашу ветвь развития. Прежде чем это сделать, он случайно объединил ветвь признаков (которая не должна быть объединена) и продолжала работать над этими изменениями, генерируя пару коммитов после слияния.
Теперь мы хотим сохранить эти изменения, но применим их к фиксации до того, как было выполнено слияние. Чтобы было ясно:
A (+b, +a)
|
B (+a)
|
C (merge commit)
|\
D \
| E (feature branch)
| /
|/
F
Мы хотим, чтобы его изменения (+ a, + b) были применены к commit D. Эквивалент:
C (+a,+b)
|
D
| E (feature branch)
| /
|/
F
Как мы можем внести изменения, чтобы отклонить предыдущее слияние, сохраняя локальные изменения?
Ответы
Ответ 1
Это задание для git rebase -i
. Run:
git rebase -i F
Вам будет представлен список коммитов в ${EDITOR}
, например:
pick 334ad92 D
pick fb54c42 E
pick 6901e51 B
pick 6c61a52 A
# Rebase eea2847..6c61a52 onto eea2847
#
# (more instructions here)
Удалите строку pick fb54c42 E
, чтобы удалить эту фиксацию. (Кроме того, если вы хотите, чтобы A
и B
объединялись в одно коммит, вы можете изменить команду pick
на squash
- squash 6c61a52 A
). Сохраните и закройте файл, и ваши ветки будут в состоянии, которое вы хотите.
Обратите внимание, что это изменит историю. Это означает, что вам нужно сделать git push -f
, если вы уже нажали на ветку в любом месте, и это будет бесполезно с кем-либо, кто сотрудничал в этой ветке. Если это проблема, вы можете git revert
выполнить слияние:
git revert -m 1 C
Аргумент -m 1
сообщает git о возврате против первого родителя коммита, который является стороной, которая была объединена (D
, на вашей диаграмме).
Ответ 2
Я не понимаю, в каком направлении находится временная шкала в ваших примерах (которые совершаются, прежде чем), поэтому я объясню в общих чертах:
- Выделите новую ветку с фиксацией до объединения и проверьте ее.
-
git cherry-pick A
и B
, чтобы внести изменения, внесенные девеопером в фиксацию слияния.
- Черри-выберите любые коммиты, произошедшие после слияния.
Теперь ваша новая ветвь содержит историю, как она должна смотреть, чтобы теперь вы могли git reset --hard
исходную ветвь перейти в это состояние. Имейте в виду, что принудительное нажатие на общий репозиторий и извлечение его другими разработчиками будет иметь для них очевидные последствия: каждый должен будет git rebase
выполнить любую работу, основанную на старом состоянии этой ветки, в новом состоянии.
Вы также можете "отменить" ветвь с ветвью "фиксированной". Как я уже сказал, я не видел, был ли он раздвоен до совершения оскорбления. Если это было сделано раньше, вам не потребуется исправлять ветвь функции.
Ответ 3
Используйте git revert C
, чтобы отменить фиксацию слияния C (вам, возможно, придется пройти -m 1
, чтобы Git знал, какую сторону слияния сохранить). См. Как восстановить неверное слияние для получения подробной информации и уточнения того, что произойдет, если вы продолжите работу над ветвью функций, а затем решите снова объединить ее.
Возвратный подход не дает вам именно то, что вы просите; коммиты, внесенные слиянием, по-прежнему будут частью истории проекта, но их изменения исчезнут. Чтобы избавиться от коммитов и слияния в целом, потребуется перебазировать (и описано в ответе Эш Уилсон), что требует тщательного рассмотрения и обычно не стоит усилий, если только не существуют юридические ограничения или технические проблемы (например, гигантские двоичные файлы) с фиксацией который прибыл через фиксацию слияния.
Ответ 4
Если у вас есть локальный репозиторий, а не удаленный репозиторий, это было бы легко.
локальная
- feature-branch - обновлено с нарушенным/неправильным фиксацией *
- master - объединено
удаленный
- feature-branch - обновлено
- мастер - не объединенный
Если это сценарий, вам просто нужно удалить как локальную ветвь функции, так и мастер, а затем получить/проверить из удаленного репозитория.
Надеюсь, что это все еще помогает.:)