1 июня 2013 г.

Git: Объединение merge коммитов

Возникла у меня на работе необходимость объединить два merge в один. Делал большое и несколько конфликтное слияние. А во время этого в Gerrit на мою ветку успели залить что-то новое, вызвавшее новые конфликты с моим merge. Соответственно необходимо было слить эти изменения тоже. На тот момент я видел следующие варианты:

  • Самый простой способ: сделать еще один merge. В итоге получаем еще один дополнительный commit и разветвленную историю.
  • Сделать полный merge заново. Повторять уже сделанное не хочется.

Я решил найти вариант, позволяющий в результате первого простого способа получить один коммит. Оказалось эта операция не совсем очевидна. Как всегда в последнее время, нашел решение на stackoverflow. Опишу весь процесс с начала до конца с историей тестового репозитория (git log --oneline --graph --decorate):

  • Итак, мы сделали какой-то абстрактный merge master в feature ветку с исправлением всех конфликтов:
$ git checkout feature
$ git merge origin/master
*   b8c37f7 (HEAD, feature) c'
|\
| * 7020561 (origin/master) b
* | 2a55e67 (origin/feature) b'
|/
* b888f61 a
  • Далее кто-то добавил что-то новое на feature ветку:
* 3820f07 (origin/feature) c'
| *   b8c37f7 (HEAD, feature) c'
| |\
|/ /
| * 7020561 (origin/master) b
* | 2a55e67 b'
|/
* b888f61 a
  • Делаем дополнительный merge и видим не особо приятную историю:
$ git merge origin/feature
*   781dea7 (HEAD, feature) d'
|\
| * 3820f07 (origin/feature) c'
* |   b8c37f7 c'
|\ \
| |/
|/|
| * 7020561 (origin/master) b
* | 2a55e67 b'
|/
* b888f61 a
  • А теперь собственно решение с выправлением истории. Делаем reset на коммит, с которого надо делать merge:
$ git reset --soft origin/feature
* 3820f07 (HEAD, origin/feature, feature) c'
* 2a55e67 b'
| * 7020561 (origin/master) b
|/
* b888f61 a
  • Далее симулируем merge с origin/master и делаем commit:
$ git rev-parse origin/master > .git/MERGE_HEAD
$ git commit
*   3b01bf0 (HEAD, feature) d'
|\
| * 7020561 (origin/master) b
* | 3820f07 (origin/feature) c'
* | 2a55e67 b'
|/
* b888f61 a

Как видим в итоге получилась аккуратная история с необходимым полным слиянием веток. Теперь можно делать push. Данный способ можно использовать для объединения любого количества merge коммитов.

По идее надо запрещать людям добавлять новые изменения во время крупных слияний. Так будет возникать меньше затруднительных ситуаций.

Комментариев нет: