La commande que vous recherchez est git rebase
, en particulier, l' -i/--interactive
option.
Je vais supposer que vous voulez laisser le commit c sur la branche A, et que vous voulez vraiment dire que vous voulez déplacer les autres commits vers les autres branches, plutôt que de fusionner, car les fusions sont simples. Commençons par manipuler la branche A.
git rebase -i <SHA1 of commit a>^ branchA
Le ^
signifie le commit précédent, donc cette commande dit de rebaser la branche A en utilisant le commit avant "a" comme base. Git vous présentera une liste des commits dans cette plage. Réorganisez-les et dites à git d'écraser les bons:
pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f
Maintenant, l'histoire devrait ressembler à ceci:
c - [a+d+e+g] - [b+f] (branchA)
/
--o-x-x-x-x-x-x-x-x-x-x (master)
Maintenant, prenons le commit b + f nouvellement écrasé pour branchB.
git checkout branchB
git cherry-pick branchA # cherry-pick one commit, the tip of branchA
Et pareil pour a + d + e + g pour master:
git checkout master
git cherry-pick branchA^
Enfin, mettez à jour branchA pour qu'il pointe vers c:
git branch -f branchA branchA^^
Nous devrions maintenant avoir:
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)
Notez que si vous avez plusieurs commits que vous souhaitez déplacer entre les branches, vous pouvez utiliser rebase à nouveau (de manière non interactive):
# 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
Enfin, un avertissement: il est tout à fait possible de réorganiser les commits de telle sorte que certains ne s'appliquent plus proprement. Cela peut être dû au fait que vous avez choisi un mauvais ordre (mettre un correctif avant le commit introduisant la fonctionnalité qu'il a corrigée); dans ce cas, vous voudrez abandonner le rebase ( git rebase --abort
). Sinon, vous devrez résoudre intelligemment les conflits (comme vous le faites avec les conflits de fusion), ajouter les correctifs, puis exécuter git rebase --continue
pour passer à autre chose. Ces instructions sont également fournies par le message d'erreur imprimé lorsque le conflit se produit.