Git cherry-pick : plusieurs commits, branches, conflits
git cherry-pick : copier un commit depuis une autre branche, en prendre plusieurs ou une plage, régler les conflits, et savoir quand merge ou rebase gagne.
TL;DR : git cherry-pick <sha> copie un commit de n'importe quelle branche sur ta branche courante — même patch, nouveau SHA, aucun historique déplacé. Pour plusieurs commits, liste les SHA ou utilise une plage (git cherry-pick A..B) ; note que la plage exclut A, donc écris A^..B pour l'inclure. Si ça s'arrête sur un conflit : résous, git add, puis git cherry-pick --continue. Le cherry-pick sert à déplacer un correctif précis — quand tu veux tout ce que contient l'autre branche, passe par merge ou rebase.
Que fait exactement git cherry-pick ?
Le cherry-pick prend un commit existant et applique son diff comme un nouveau commit sur ta branche courante. Le commit d'origine reste où il est ; la copie reçoit un SHA tout frais. Git ne « déplace » rien — ceux qui se demandent plus tard pourquoi le commit apparaît toujours sur l'ancienne branche voient exactement ça.
Ce modèle copier-sans-déplacer décide de quand le cherry-pick est le bon outil :
- Tu as besoin d'un correctif d'une branche de fonctionnalité sur
mainmaintenant, sans merger le reste. - Un hotfix commité sur la mauvaise branche doit atterrir sur la bonne.
- Un patch doit être rejoué sur une branche de release qui ne merge jamais depuis
main.
La compétence complémentaire est de savoir annuler un commit qui s'est révélé mauvais — la mécanique est couverte dans git undo last commit : garder les modifications.
Comment cherry-picker un commit d'une autre branche ?
Trouve le SHA, bascule sur la branche cible, pick :
# 1. Repérer le commit sur la branche source
git log feature/payment-fix --oneline -5
# 2. Basculer sur la branche qui doit le recevoir
git switch main
# 3. Le copier par-dessus
git cherry-pick 1a2b3c4
Deux commodités à connaître :
git cherry-pick <branch>pick le commit de pointe de cette branche — pratique, mais facile à déclencher par accident avec une image mentale périmée de ce qu'est « la pointe ».- Après le pick,
git log -1 --statconfirme ce qui est arrivé. Une seconde de lecture, qui épargne un revert.
Les commits restent sur feature/payment-fix ; supprime cette branche quand tu veux — la copie pickée sur main a son propre SHA et aucune dépendance à l'ancien.
Comment cherry-picker plusieurs commits ?
Trois formes, par fréquence à laquelle tu les voudras :
Les trois marchent aussi entre branches : les SHA se résolvent dans tout le dépôt, donc les commits peuvent venir de n'importe quelle branche — il suffit d'être placé sur la branche qui les reçoit.
# 1. Liste explicite — pickés dans l'ordre où tu les listes
git cherry-pick 1a2b3c4 5d6e7f8
# 2. Plage — tout ce qui suit A jusqu'à B inclus
git cherry-pick A..B
# 3. Plage incluant A
git cherry-pick A^..B
La distinction A..B vs A^..B est la surprise classique : A..B exclut A. Si tu visualises la plage depuis git log et pick oldest..newest, tu sautes silencieusement le commit le plus ancien. Quand l'objectif est « les quelques plus vieux commits, dans l'ordre », écris oldest^..newest et le décalage de un disparaît.
Pour replier plusieurs picks en un seul commit au lieu de trois, stage sans committer avec -n / --no-commit, puis commit une fois :
git cherry-pick -n 1a2b3c4 5d6e7f8
git commit -m "Backport: payment retry fixes"
Pourquoi git cherry-pick ne fonctionne-t-il pas ?
Quatre causes réelles, par fréquence :
1. Un conflit a arrêté le pick. Git applique le patch, tombe sur une ligne modifiée des deux côtés, et se met en pause en pleine séquence :
# résous les fichiers, puis :
git add <resolved-files>
git cherry-pick --continue # ou --abort pour revenir à l'état d'avant le pick
--continue n'est ni optionnel ni implicite — tant que tu ne le lances pas, tu es au milieu d'une séquence cherry-pick en pause et git status continuera de le dire.
2. Le pick est vide (« The previous cherry-pick is now empty »). Le changement existe déjà sur cette branche, souvent à cause d'un pick antérieur ou d'un merge squashé. Passe-le avec git cherry-pick --skip, ou force un commit vide avec --allow-empty si tu as vraiment besoin du marqueur.
3. Le commit est un merge commit. Un merge a deux parents, donc « applique ce diff » est ambigu — git refuse plutôt que de deviner. Dis quel parent tu prends comme référence :
git cherry-pick -m 1 <merge-sha> # parent 1 = la branche *dans* laquelle on a mergé
4. Mauvais working tree ou HEAD détachée. Le pick atterrit où que HEAD pointe. git branch --show-current avant de picker ; si ça n'imprime rien, tu es en HEAD détachée et le commit sera orphelin quand tu basculeras ailleurs.
Cherry-pick vs merge vs rebase : lequel, quand ?
| Commande | Ce qui arrive sur la cible | Historique | À utiliser quand |
|---|---|---|---|
git cherry-pick <sha> |
Le(s) commit(s) nommé(s) seulement | Copie, nouveaux SHA | Un correctif précis doit bouger maintenant |
git merge <branch> |
Tout ce qu'il y a sur la branche | Merge commit ou fast-forward | Tu veux toute la branche, divergence visible |
git rebase <base> |
Tous les commits de la branche, rejoués | Linéaire, SHAs réécrits | Tu veux la branche comme une suite linéaire propre |
git revert <sha> |
L'inverse d'un commit | Ajoute un commit d'annulation | Un commit déjà arrivé doit être annulé sur un historique partagé |
La règle en une ligne : le cherry-pick déplace une sélection ; merge et rebase déplacent tout. Sortir le cherry-pick pour « synchroniser » avec une branche signale que tu veux en fait un merge — et si la branche est le main de ton fork face à l'upstream, la routine complète est dans synchroniser un fork avec upstream, pas à pas.
Une habitude à sauter : cherry-picker le même commit dans plusieurs branches sur le long terme. Chaque futur correctif de la branche source demandera un autre pick, et les branches finissent par diverger. Les backports vers des branches de release sont un motif normal ; un univers parallèle permanent, non.
Le workflow cherry-pick, en résumé
git log <source-branch> --oneline -5 # trouver le(s) SHA
git switch <target-branch> # atterrir au bon endroit
git cherry-pick A^..B # plage, liste, ou SHA unique
# en cas de conflit : résoudre → git add → git cherry-pick --continue
git log -1 --stat # confirmer ce qui est arrivé
Trouver, basculer, picker, vérifier. La commande a une réputation de danger qu'elle ne mérite pas — soit le diff s'applique, soit ça s'arrête et te dit pourquoi. La seule erreur réellement destructive est de picker dans la mauvaise branche, et git log -1 avant le push rend celle-ci difficile à rater.