Большинство методов будет несколько болезненным. Существует умеренно безболезненная версия, использующая git filter-branch
, за исключением того, что сама фильтрующая ветвь болезненна. :-) (вы фильтр совершает F
и G
и написать коммит-фильтр, который заменяет в новых родителей, которые вы хотите для F'
, и пусть работа фильтра-ветви заменить отцовство для G
.)
Я думаю, Простейший метод, который не прибегает к командам низкого уровня, - это просто создать новое слияние, а затем перезагрузить G
на новое слияние. Новое слияние может иметь конфликты, но мы не заботимся, мы просто хотим взять дерево старого Merge, которые мы можем сделать так:
$ git checkout <sha1> # Use D or E's sha-1 here.
# Note: whichever you use will
# be the first parent of our new
# merge; choose based on that.
$ git merge --no-commit <sha1> # use the remaining sha-1 here
[ignore resulting stuff]
$ git rm -rf . # Note: assumes you're in top dir of work tree
$ git checkout <sha1-of-F> -- .
$ git commit # Create merge commit F'
первым checkout
получает вас на отдельный РУКОВОДИТЕЛЬ с одним SHA- 1, merge --no-commit
запускает процесс слияния с другим SHA-1, git rm -rf .
выбрасывает объединенное дерево и любые конфликты, а git checkout <id> -- .
заполняет индекс и рабочее дерево из предыдущего слияния. Финал git commit
создает слияние F'
с тем же деревом, что и слияние F
, но с разными родителями.
На данный момент (все еще с отсоединенной головкой) вы можете переустановить (или вишневое) совершить G
(или много коммитов G
), а затем заставьте свою ветвь указывать на кончик нового графика. Я бы предложил использовать git rebase ... --onto HEAD
, но я не тестировал это с отдельной головкой, и есть хотя бы один способ, которым это может пойти не так (разрешение HEAD
на ID слишком поздно).
Команда нижнего уровня git commit-tree
может быть даже проще. Andrew C wrote the correct command in a comment, хотя вы должны указать название филиала git update-ref
. [Изменить: возможно, не совсем правильно, два родителя, которых вы хотите, - D
и E
, а не D
и B
. Опять же, поставьте тот, который вы хотите, в качестве первого родителя.]
Преимущество (?) Использования более знакомых команд в том, что они, ну, более знакомы.
Что-то вроде 'git update-ref feature_branch $ (git commit-tree -p E -p B -m" fakeout merge "F^{tree})', а затем 'git cherry-pick G' должен работать –
@AndrewC для копирования сообщения фиксации 'git show -s -pretty =% BF' | git commit-tree и т. д. '. – jthill