Qu'est-ce que Git Cherry-Pick ?
Un correctif critique vient d'arriver sur votre branch de développement -- mais le même bug est en production. Vous ne pouvez pas merge toute la branch de développement dans la branch de release, car elle est pleine de fonctionnalités à moitié terminées. Ce dont vous avez réellement besoin, c'est de prendre ce commit précis et de l'appliquer ailleurs. C'est exactement ce que fait git cherry-pick.
Le cherry-pick prend les modifications introduites par un commit existant et les rejoue sur votre branch actuelle sous la forme d'un tout nouveau commit. Le nouveau commit contient le même diff et, par défaut, le même message, mais il a un parent différent et donc un SHA différent. Ce détail compte plus qu'il n'y paraît : Git identifie les commits par leur SHA, donc après un cherry-pick votre dépôt contient deux commits distincts qui introduisent la même modification. Gardez cela en tête -- cela explique à la fois pourquoi le cherry-pick est si utile et pourquoi en abuser cause des problèmes plus tard.
Quand le cherry-pick est le bon outil
Rétroporter un hotfix vers une branch de release
C'est le cas classique. Vous avez corrigé un bug sur main, mais c'est la version 2.3 que vos utilisateurs utilisent, et ils ont besoin du correctif maintenant. Faites un cherry-pick du correctif sur la branch de release :
git switch release/2.3
git cherry-pick a1b2c3d
La branch de release reçoit exactement ce correctif, et rien d'autre de main ne s'invite au passage.
Un commit a atterri sur la mauvaise branch
Vous vouliez faire un commit sur votre branch de fonctionnalité, mais vous étiez sur main. Le cherry-pick offre une récupération propre : passez sur la branch où le commit doit aller, faites-y le cherry-pick, puis revenez le supprimer de la branch où il n'a rien à faire. Si cette étape de suppression vous semble incertaine, notre guide sur comment annuler un commit Git détaille chaque option.
Sauver un correctif d'une branch abandonnée
Parfois une expérimentation ne donne rien, mais un commit au milieu de la branch corrigeait un vrai bug. Au lieu de merge une branch sans avenir, faites un cherry-pick du seul commit qui a de la valeur sur votre branch active et laissez le reste de l'expérimentation être supprimé en paix.
Utilisation de base
La forme la plus simple prend un seul commit :
git cherry-pick a1b2c3d
Git applique les modifications de ce commit et crée immédiatement un nouveau commit sur votre branch actuelle, en réutilisant le message d'origine. Vous pouvez aussi passer plusieurs commits à la fois, et Git les applique un par un, dans l'ordre où vous les listez :
git cherry-pick a1b2c3d f4e5d6c
Les options pratiques à connaître
-x : enregistrer l'origine du commit
Lors d'un rétroportage, vous voudrez plus tard savoir d'où vient un commit. L'option -x ajoute une ligne comme (cherry picked from commit a1b2c3d...) au message du nouveau commit :
git cherry-pick -x a1b2c3d
Faites-en une habitude pour tout cherry-pick entre des branches publiques de longue durée. Dans six mois, cette simple ligne vous dira instantanément si un correctif est arrivé dans une release et d'où il provient.
Prendre une plage de commits
Vous pouvez faire un cherry-pick d'une plage entière avec la syntaxe à deux points :
git cherry-pick A..B
Attention : cela applique les commits situés après A, jusqu'à B inclus. A lui-même est exclu. Si vous voulez inclure A, écrivez :
git cherry-pick A^..B
Le ^ signifie « le parent de A », ce qui remet A dans la plage. Confondre ces deux syntaxes est l'une des erreurs de cherry-pick les plus courantes.
--no-commit : appliquer sans commiter
Parfois vous voulez les modifications mais pas de commit automatique -- par exemple pour combiner plusieurs commits récupérés en un seul, ou pour ajuster le résultat avant de commiter :
git cherry-pick --no-commit a1b2c3d
Les modifications arrivent dans votre répertoire de travail et en staging, et vous créez le commit vous-même quand vous êtes prêt.
Gérer les conflits pendant un cherry-pick
Un cherry-pick peut entrer en conflit pour la même raison qu'un merge : le commit que vous récupérez a été écrit sur un code différent de celui de votre branch actuelle. Quand cela arrive, Git s'arrête en pleine opération et marque les fichiers en conflit :
error: could not apply a1b2c3d... fix login timeout
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue"
Vous avez alors trois portes de sortie :
git cherry-pick --continue-- après avoir édité les fichiers en conflit et les avoir mis en staging avecgit add, cette commande termine le cherry-pick et crée le commit.git cherry-pick --abort-- annule toute l'opération et ramène votre branch exactement dans l'état où elle était avant de commencer. Rien n'est perdu, rien n'est appliqué.git cherry-pick --skip-- lors de la récupération de plusieurs commits, ignore le commit en cours et passe au suivant. Utile quand un commit de la plage s'avère déjà appliqué ou sans intérêt.
La résolution des conflits elle-même fonctionne exactement comme pour un conflit de merge : ouvrez chaque fichier en conflit, choisissez entre les hunks concurrents (ou combinez-les), supprimez les marqueurs de conflit et mettez le fichier en staging. Si les marqueurs de conflit vous intimident encore, notre guide pour résoudre visuellement les conflits de merge Git s'applique aussi aux cherry-picks.
Ce qu'il ne faut PAS faire avec cherry-pick
Ne faites pas de cherry-pick de branches entières
Si vous vous retrouvez à faire des cherry-picks de cinq, dix, vingt commits d'une branch vers une autre, arrêtez-vous. C'est à cela que servent merge et rebase. Les deux déplacent du travail entre branches tout en laissant Git comprendre la relation qui les lie, ce qui garde les opérations futures simples et sans conflits. Si vous hésitez entre les deux, notre comparatif rebase vs merge passe en revue les compromis.
L'historique dupliqué vous rattrape plus tard
Rappelez-vous : un cherry-pick crée un nouveau commit avec un nouveau SHA, et Git ne conserve aucune trace formelle indiquant que les deux commits représentent « la même modification ». Si vous faites des cherry-picks de commits d'une branch de fonctionnalité vers main puis que vous finissez par merge cette branch quand même, Git doit réconcilier deux copies des mêmes modifications. Souvent, il y parvient discrètement. Mais dès que l'une des copies a été modifiée entre-temps, vous obtenez des conflits déroutants où les deux côtés semblent presque identiques -- et votre historique montre la même modification deux fois, avec deux dates et deux SHA, ce qui complique l'usage d'outils comme git log et git bisect.
Une bonne règle : le cherry-pick sert à déplacer des exceptions -- un hotfix, un commit égaré, un correctif sauvé. Dès qu'il devient votre méthode habituelle pour déplacer du travail entre branches, votre historique vous signale que la stratégie de branches mérite d'être repensée.
Le cherry-pick dans GitSquid
Dans GitSquid, le cherry-pick se trouve là où vous l'attendez : faites un clic droit sur n'importe quel commit du graphe de commits et choisissez l'option cherry-pick dans le menu contextuel. Plus besoin de copier des SHA entre un log et un terminal.
Le vrai gain, c'est de savoir où vous mettez les pieds. Le Conflict Predictor de GitSquid -- gratuit pour tout le monde -- montre exactement quels fichiers entreront en conflit avant de lancer un merge, un rebase ou un cherry-pick, avec aperçu des hunks et coloration syntaxique. Au lieu de découvrir les conflits au milieu d'une opération, vous les voyez à l'avance et pouvez décider de continuer, de choisir un autre commit, ou de préparer la résolution sereinement.
Et quand un cherry-pick entre malgré tout en conflit, « Resolve in scratch worktree » ouvre un worktree temporaire dans un nouvel onglet, pour que vous puissiez tout résoudre là-bas pendant que votre checkout actif reste intact.
Référence rapide
| Commande | Ce qu'elle fait |
|---|---|
git cherry-pick <sha> |
Applique un commit sur la branch actuelle |
git cherry-pick <sha1> <sha2> |
Applique plusieurs commits, dans l'ordre |
git cherry-pick -x <sha> |
Ajoute le SHA d'origine au message du commit |
git cherry-pick A..B |
Prend les commits après A jusqu'à B (A exclu) |
git cherry-pick A^..B |
Prend la plage en incluant A |
git cherry-pick --no-commit <sha> |
Applique les modifications sans commiter |
git cherry-pick --continue |
Termine le cherry-pick après résolution des conflits |
git cherry-pick --abort |
Annule et restaure la branch telle qu'elle était |
git cherry-pick --skip |
Ignore le commit en cours, continue avec le reste |
Le cherry-pick est un scalpel, pas une pelle. Utilisé pour une extraction précise et occasionnelle -- un rétroportage de hotfix, un commit égaré, un correctif sauvé -- c'est l'une des commandes les plus satisfaisantes de Git. Utilisé comme substitut au merge, il remplit discrètement votre historique de doublons qui reviendront vous hanter. Sachez faire la différence, ajoutez -x quand vous rétroportez, et gardez --abort en tête comme porte de secours.
Envie de voir quels fichiers entreront en conflit avant même de commencer ? Téléchargez GitSquid gratuitement et laissez le Conflict Predictor éliminer les mauvaises surprises de votre prochain cherry-pick.