Подтвердить что ты не робот

Удалите слияние, сохраняя текущие изменения

У нас была небольшая проблема в нашей команде. Один разработчик должен был внести некоторые изменения в нашу ветвь развития. Прежде чем это сделать, он случайно объединил ветвь признаков (которая не должна быть объединена) и продолжала работать над этими изменениями, генерируя пару коммитов после слияния.

Теперь мы хотим сохранить эти изменения, но применим их к фиксации до того, как было выполнено слияние. Чтобы было ясно:

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

Как мы можем внести изменения, чтобы отклонить предыдущее слияние, сохраняя локальные изменения?

4b9b3361

Ответ 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 - обновлено
  • мастер - не объединенный

Если это сценарий, вам просто нужно удалить как локальную ветвь функции, так и мастер, а затем получить/проверить из удаленного репозитория.

Надеюсь, что это все еще помогает.:)