// GitHub & Git

git rebase et cherry-pick expliqués

git rebase et git cherry-pick sont deux commandes qui réécrivent l’historique d’un dépôt Git. Bien maîtrisées, elles produisent un historique propre et linéaire, facile à relire. Mal utilisées, elles peuvent semer la confusion dans une équipe. Ce guide explique leur fonctionnement, quand les employer, comment résoudre les conflits qu’elles génèrent, et surtout la règle d’or à ne jamais transgresser. Si les bases de Git vous manquent, commencez par notre article sur les commandes Git essentielles.

Qu’est-ce que rebaser ?

Rebaser, c’est déplacer une série de commits pour les rejouer à partir d’un autre point de départ. Là où merge fusionne deux branches en créant un commit de fusion, rebase réapplique vos commits un à un au sommet de la branche cible, comme si vous aviez travaillé à partir de sa dernière version.

Concrètement, imaginez une branche feature partie de main. Entre-temps, main a avancé. Deux façons d’intégrer ces nouveautés :

# Depuis la branche feature
git rebase main

Git prend vos commits de feature, les met de côté, avance feature au niveau de main, puis rejoue vos commits par-dessus. Résultat : un historique linéaire, sans commit de fusion.

rebase contre merge

Les deux intègrent les changements d’une branche dans une autre, mais produisent un historique différent.

La fusion (merge)

git checkout main
git merge feature

merge préserve l’historique exact : on voit que feature a existé en parallèle, et un commit de fusion relie les deux branches. L’historique est fidèle mais peut devenir touffu, avec de multiples branches entrelacées.

Le rebase

git checkout feature
git rebase main

rebase réécrit les commits pour donner l’illusion d’un développement séquentiel. L’historique est propre et linéaire, plus facile à lire avec git log --oneline --graph.

Lequel choisir ?

  • merge quand vous voulez conserver la trace fidèle de ce qui s’est passé, notamment sur les branches partagées et pour intégrer une pull request.
  • rebase pour nettoyer votre branche locale avant de la partager, ou pour mettre à jour votre travail avec main sans polluer l’historique de commits de fusion.

Une pratique répandue : rebaser sa branche de fonctionnalité sur main régulièrement en local, puis la fusionner une fois prête. On combine ainsi historique propre et traçabilité de l’intégration.

Le rebase interactif

Le rebase interactif (-i) est l’outil le plus puissant pour remanier votre historique local. Il ouvre un éditeur listant les commits à retravailler.

# Retravailler les 4 derniers commits
git rebase -i HEAD~4

Git affiche une liste de ce type :

pick a1b2c3d Ajoute le formulaire de contact
pick e4f5g6h Corrige typo
pick i7j8k9l Ajoute la validation
pick m0n1o2p wip

# Commands:
# p, pick   = utiliser le commit
# r, reword = utiliser le commit, mais éditer le message
# e, edit   = utiliser le commit, mais s'arrêter pour l'amender
# s, squash = fusionner dans le commit précédent
# f, fixup  = comme squash mais jette le message
# d, drop   = supprimer le commit

On modifie les mots-clés en début de ligne pour indiquer l’action souhaitée, puis on sauvegarde et ferme l’éditeur. Git rejoue alors les commits selon vos instructions.

squash : regrouper des commits

squash (ou fixup) fusionne plusieurs commits en un seul. Idéal pour transformer une série de « wip », « corrige typo », « oups » en un commit propre.

pick a1b2c3d Ajoute le formulaire de contact
squash e4f5g6h Corrige typo
squash i7j8k9l Ajoute la validation

Les trois deviennent un unique commit. Avec squash, Git vous laisse rédiger le message combiné ; avec fixup, il garde seulement le message du premier.

reword : réécrire un message

reword conserve le contenu du commit mais vous laisse réécrire son message.

reword a1b2c3d Ajoute le formulaire de contact

Git s’arrête à ce commit et ouvre l’éditeur pour corriger le message. Parfait pour clarifier une description bâclée.

edit : modifier le contenu d’un commit

edit interrompt le rebase à ce commit pour vous permettre d’en changer le contenu (ajouter un fichier oublié, corriger une ligne).

# Le rebase s'arrête au commit marqué "edit"
# Faites vos modifications, puis :
git add fichier-oublie.js
git commit --amend
git rebase --continue

drop : supprimer un commit

Remplacer pick par drop (ou simplement supprimer la ligne) retire le commit de l’historique.

pick a1b2c3d Ajoute le formulaire de contact
drop m0n1o2p wip

Réordonner les commits

Il suffit de déplacer les lignes dans l’éditeur pour changer l’ordre des commits. Git les rejouera dans le nouvel ordre — attention, cela peut générer des conflits si les commits touchent les mêmes lignes.

git cherry-pick

cherry-pick applique un commit précis d’une branche sur votre branche actuelle, sans fusionner le reste. C’est l’outil de la sélection chirurgicale.

# Applique le commit a1b2c3d sur la branche courante
git cherry-pick a1b2c3d

Git crée un nouveau commit avec les mêmes modifications (mais un hash différent, puisqu’il est appliqué à un autre endroit).

Cas d’usage typiques

  • Rétroporter un correctif : un bug est corrigé sur main, et il faut appliquer ce seul correctif sur une branche de release v2.1.
  • Récupérer un commit d’une branche abandonnée sans tout fusionner.
  • Déplacer un commit fait par erreur sur la mauvaise branche.
# Rétroporter un correctif sur une ancienne version
git checkout release-2.1
git cherry-pick a1b2c3d   # le commit de correction de bug

Cherry-pick de plusieurs commits

git cherry-pick a1b2c3d e4f5g6h        # deux commits précis
git cherry-pick a1b2c3d^..i7j8k9l       # une plage de commits

Deux options utiles : -n (ou --no-commit) applique les changements sans créer de commit, pour les regrouper ; -x ajoute une ligne « (cherry picked from commit …) » au message, traçant l’origine.

git cherry-pick -x a1b2c3d

Résoudre les conflits

Rebase et cherry-pick rejouent des commits : si une modification entre en collision avec l’état de la branche, Git s’arrête sur un conflit. La démarche est la même dans les deux cas.

Git marque les zones conflictuelles dans les fichiers concernés :

<<<<<<< HEAD
const titre = "Bienvenue sur le site";
=======
const titre = "Bienvenue chez nous";
>>>>>>> a1b2c3d (Change le titre)

La marche à suivre :

# 1. Voir les fichiers en conflit
git status

# 2. Éditer chaque fichier : garder la bonne version,
#    supprimer les marqueurs <<<<<<<, =======, >>>>>>>

# 3. Marquer le fichier comme résolu
git add fichier-en-conflit.js

# 4. Poursuivre l'opération
git rebase --continue     # ou : git cherry-pick --continue

Deux échappatoires en cas de doute :

git rebase --skip       # ignore le commit courant et passe au suivant
git rebase --abort      # annule tout et revient à l'état initial

--abort est votre filet de sécurité : il restaure la branche telle qu’elle était avant le rebase. Si une opération tourne mal malgré tout, git reflog permet de retrouver n’importe quel état antérieur — un sujet développé dans notre guide pour annuler et défaire avec Git.

Réduire la douleur des conflits

  • Rebasez souvent : de petits rebase fréquents génèrent moins de conflits qu’un gros rebase après des semaines de divergence.
  • Activez rerere pour que Git mémorise vos résolutions et les rejoue automatiquement : git config --global rerere.enabled true.
  • Faites des commits atomiques : un commit = un changement cohérent, plus facile à rejouer.

La règle d’or : ne jamais rebaser du public

C’est la règle la plus importante de tout ce guide. Ne rebasez jamais des commits déjà poussés et partagés avec d’autres.

Rebaser réécrit l’historique : les commits changent de hash. Si un collègue a déjà récupéré ces commits, votre historique réécrit divergera du sien. Au prochain pull, Git verra deux historiques incompatibles, générant des doublons et une confusion générale.

# DANGEREUX si la branche est partagée
git checkout main
git rebase autre-branche
git push --force   # écrase l'historique distant : à proscrire sur une branche commune

Le repère simple

  • Branche locale, non poussée, ou personnelle → rebase autorisé et recommandé pour nettoyer.
  • Branche partagée (main, develop, une branche sur laquelle un collègue travaille)jamais de rebase. Utilisez merge.

Si vous devez absolument republier une branche de fonctionnalité personnelle après un rebase, préférez --force-with-lease à --force : il refuse le push si quelqu’un d’autre a poussé entre-temps, évitant d’écraser son travail par mégarde.

git push --force-with-lease

À retenir

rebase rejoue vos commits sur une nouvelle base pour un historique linéaire ; merge préserve la trace exacte avec un commit de fusion. Le rebase interactif (-i) permet de squash, reword, edit, drop et réordonner vos commits locaux avant partage. cherry-pick applique un commit isolé sur la branche courante, parfait pour rétroporter un correctif. En cas de conflit, résolvez, git add, puis --continue — ou --abort pour tout annuler. Et surtout, gravez la règle d’or : réécrire l’historique est un plaisir tant qu’il reste local.

À lire ensuite