Восстановление ветки git после ошибочного слияния (с учетом коммитов слияния) - PullRequest
1 голос
/ 04 июля 2019

У меня классическая ситуация: я слил ветку 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^, это было бы слишком просто.

1 Ответ

0 голосов
/ 04 июля 2019

На основании https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt, Я бы

git checkout dev
$EDITOR files
git commit files -m 'Fix'
git checkout master
git revert W
git merge dev

Возврат-возврат необходим для сохранения изменений при повторном слиянии.

...