O comando que você está procurando é git rebase
, especificamente a -i/--interactive
opção.
Vou assumir que você deseja deixar o commit c no branch A, e que você realmente quer mover os outros commits para os outros branches, ao invés de fazer a fusão, uma vez que as fusões são diretas. Vamos começar manipulando o branch A.
git rebase -i <SHA1 of commit a>^ branchA
Os ^
meios cometem o anterior, então este comando diz para rebase ramo Um usando o commit antes "a" como a base. O Git apresentará uma lista de commits neste intervalo. Reordene-os e diga ao git para esmagar os apropriados:
pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f
Agora, a história deve ser semelhante a esta:
c - [a+d+e+g] - [b+f] (branchA)
/
--o-x-x-x-x-x-x-x-x-x-x (master)
Agora, vamos pegar o commit recém-comprimido b + f para branchB.
git checkout branchB
git cherry-pick branchA # cherry-pick one commit, the tip of branchA
E o mesmo para a + d + e + g para mestre:
git checkout master
git cherry-pick branchA^
Finalmente, atualize branchA para que aponte para c:
git branch -f branchA branchA^^
Devemos agora ter:
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)
Observe que se você tiver vários commits que deseja mover entre branches, poderá usar o rebase novamente (não interativamente):
# 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
Finalmente, uma isenção de responsabilidade: é bem possível reordenar os commits de forma que alguns não se apliquem mais corretamente. Isso pode ser porque você escolheu uma ordem incorreta (colocar um patch antes do commit introduzindo o recurso que ele corrigiu); nesse caso, você deseja abortar o rebase ( git rebase --abort
). Caso contrário, você terá que consertar os conflitos de forma inteligente (assim como faz com os conflitos de mesclagem), adicionar as correções e, em seguida, correr git rebase --continue
para seguir em frente. Essas instruções também são fornecidas pela mensagem de erro impressa quando ocorre o conflito.