У меня классическая ситуация: я слил ветку dev
в master
, затем понял, что допустил ошибку, и отменил слияние. Затем добавил исправление в dev
и хочу снова объединить его. Конечно, я не могу объединить это напрямую, поскольку, с точки зрения git, оно уже было объединено.
Классическое решение
Вернуть отмененный коммит, применить исправление. Двигайся.
Что я хочу
Я хочу восстановить ветку dev
с нуля и снова объединить ее. Должно быть легко сделано с git rebase --force-rebase
, согласно книгам. Но история ветки была не так проста и содержала ряд слияний, в том числе с master
. Я хочу уважать их.
Давайте уже приведем пример:
master|
v
-*------------X-----Y---------*-----*----M-W
\ / \ \ / /
\ / \ -*- /
\ / -D- G--H-- /
\ / / \ / \ /
A--B--C-----E--F--------I-----J
^
|dev
Неисправное объединение M
. Его возврат W
. Я предполагаю, что коммиты на dev
до B
в порядке, так как B
был объединен в master
как X
. Я хочу перестроить ветку, начиная с B
с точно такой же топологией. Смотрите дерево ниже. Новые коммиты отмечены штрихом. Вы можете видеть, как коммиты A..J
были перебазированы в A'..J'
. Соответственно, dev
понижается до dev'
. Другие коммиты не изменились.
dev'|
v
A'-B'-C'----E'-F'-------I'----J'
/ \ / \ /
/ -D' G'-H'-
/ / |master
/ / v
-*------------X-----Y---------*-----*----M-W
\ / \ \ / /
\ / \ -*- /
\ / -D- G--H-- /
\ / / \ / \ /
A--B--C-----E--F--------I-----J
^
|dev
Затем я применю свое исправление K
и объединю эту новую ветку с master
:
dev'|
v
A'-B'-C'----E'-F'-------I'----J'--K
/ \ / \ / \
/ -D' G'-H'- \
/ / \ |master
/ / \v
-*------------X-----Y---------*-----*----M-W-M2
\ / \ \ / /
\ / \ -*- /
\ / -D- G--H-- /
\ / / \ / \ /
A--B--C-----E--F--------I-----J
^
|dev
Хорошо, похоже, у rebase
есть опция для этого, и она называется --rebase-merges
. Но это не делает то, что я хочу. Он отменяет все коммиты, , которые являются предками dev
и потомками B
. Который включает коммиты X
и Y
. Которые уже на master
, зачем мне их? (На самом деле, это также приносит некоторые другие коммиты из более древней истории, и я пока не понимаю, почему, но здесь дело не в этом).
Вместо этого я хочу принести коммиты, , которые являются предками dev
, но не master
(учитывая master
до ошибочного слияния, конечно). Звучит очень легко для меня. И все же я не понимаю, как это сделать, за исключением того, что вручную создаю эту разницу коммитов и каким-то образом выбираю их вручную, тщательно сохраняя родителей.
Итак, как мне перестроить мою ветку, содержащую только работу, выполненную на моей ветке и с учетом коммитов слияния?
PS Мы не можем просто сбросить master
на M^
, это было бы слишком просто.