Команда, которую вы ищете, - это git rebase
, в частности, -i/--interactive
опция.
Я собираюсь предположить, что вы хотите оставить фиксацию c в ветке A, и что вы действительно имеете в виду, что хотите переместить другие коммиты в другие ветки, а не слияние, поскольку слияние выполняется просто. Начнем с манипулирования веткой A.
git rebase -i <SHA1 of commit a>^ branchA
Это ^
означает предыдущую фиксацию, поэтому эта команда говорит, что нужно перебазировать ветку A, используя фиксацию перед «a» в качестве основы. Git представит вам список коммитов в этом диапазоне. Измените их порядок и скажите git раздавить подходящие:
pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f
Теперь история должна выглядеть так:
c - [a+d+e+g] - [b+f] (branchA)
/
--o-x-x-x-x-x-x-x-x-x-x (master)
Теперь давайте возьмем только что сжатый коммит b + f для branchB.
git checkout branchB
git cherry-pick branchA # cherry-pick one commit, the tip of branchA
И то же самое для a + d + e + g для master:
git checkout master
git cherry-pick branchA^
Наконец, обновите branchA, чтобы он указывал на c:
git branch -f branchA branchA^^
Теперь у нас должно быть:
c (branch A) - [a+d+e+g] - [b+f] (dangling commits)
/
--o-x-x-x-x-x-x-x-x-x-x-[a+d+e+g] (master)
\
x-x-x-x-x-[b+f] (branchB)
Обратите внимание, что если у вас было несколько коммитов, которые вы хотели перемещать между ветвями, вы можете снова использовать rebase (не интерактивно):
# create a temporary branch
git branch fromAtoB branchA
# move branchA back two commits
git branch -f branchA branchA~2
# rebase those two commits onto branchB
git rebase --onto branchB branchA fromAtoB
# merge (fast-forward) these into branchB
git checkout branchB
git merge fromAtoB
# clean up
git branch -d fromAtoB
Наконец, отказ от ответственности: вполне возможно изменить порядок коммитов таким образом, чтобы некоторые из них перестали применяться чисто. Это могло произойти из-за того, что вы выбрали неверный порядок (установка патча перед фиксацией, представляющая исправленную функцию); в этом случае вы захотите отменить rebase ( git rebase --abort
). В противном случае вам придется разумно исправить конфликты (как и в случае конфликтов слияния), добавить исправления, а затем запустить, git rebase --continue
чтобы двигаться дальше. Эти инструкции также содержатся в сообщении об ошибке, которое печатается при возникновении конфликта.