Aller au contenu principal

git cherry-pick & git bisect — Chirurgie de précision

Module 05 45 min

Objectifs de la section

  • Utiliser git cherry-pick pour appliquer des commits spécifiques à une autre branche
  • Utiliser git bisect pour trouver le commit qui a introduit un bug
  • Connaître les limitations et cas d'usage de ces commandes

git cherry-pick — Appliquer des commits spécifiques

git cherry-pick prend un commit d'une branche et l'applique à une autre, créant un nouveau commit avec les mêmes changements (hash différent).

Utilisation de base

# Cherry-pick d'un seul commit
git cherry-pick abc1234

# Cherry-pick de plusieurs commits
git cherry-pick abc1234 def5678 ghi9012

# Cherry-pick d'une plage de commits (exclusif du premier)
git cherry-pick abc1234..def5678

# Cherry-pick sans créer de commit (staging uniquement)
git cherry-pick --no-commit abc1234

# Cherry-pick en éditant le message de commit
git cherry-pick -e abc1234

Gérer les conflits de cherry-pick

# Si un conflit se produit :
# 1. Corriger le conflit
git status # Affiche les fichiers en conflit
# éditer les fichiers...
git add fichier-corrige.py

# 2. Continuer
git cherry-pick --continue

# OU : Abandonner
git cherry-pick --abort

# OU : Ignorer ce commit
git cherry-pick --skip

Quand utiliser cherry-pick

ScénarioUtiliser cherry-pick ?Alternative
Correction critique nécessaire sur la branche release✅ Oui-
Commit accidentellement sur la mauvaise branche✅ Oui-
Réutiliser une fonction utilitaire d'une autre branche✅ Oui-
Intégrer toute une fonctionnalité❌ NonMerge ou rebase
Synchronisation régulière des branches❌ NonMerge ou rebase
Cherry-pick vs Merge

Cherry-pick crée une copie du commit (nouveau hash). Si vous fusionnez ensuite la branche originale, Git verra ces changements en double. Utilisez cherry-pick avec parcimonie et pour des cas spécifiques.

Exemples pratiques

# Scénario 1 : Correction critique nécessaire sur la branche release
git switch release/v1.0
git cherry-pick hash-du-commit-hotfix
git push origin release/v1.0

# Scénario 2 : Commit sur la mauvaise branche
git log --oneline # Trouver le hash du commit à déplacer
git switch bonne-branche
git cherry-pick abc1234 # Appliquer sur la bonne branche
git switch mauvaise-branche
git reset HEAD~1 # Supprimer de la mauvaise branche

git bisect — Recherche binaire de bugs

git bisect effectue une recherche binaire dans votre historique de commits pour trouver le commit exact qui a introduit un bug.

Bisect manuel

# 1. Démarrer bisect
git bisect start

# 2. Marquer le commit actuel comme mauvais (bug présent)
git bisect bad

# 3. Marquer un commit connu comme bon (pas de bug)
git bisect good v1.0.0
# ou par hash :
git bisect good abc1234

# Git va checkout le commit du milieu
# Tester votre application...

# 4. Marquer chaque commit testé
git bisect good # Pas de bug sur ce commit
git bisect bad # Bug présent sur ce commit

# 5. Git trouve et affiche le commit coupable :
# abc1234 est le premier mauvais commit

# 6. Quitter bisect
git bisect reset # Retourne au HEAD original

Bisect automatisé

Si vous avez un test qui peut détecter le bug, vous pouvez automatiser complètement bisect.

Créez un script de test test_bug.sh :

#!/bin/bash
# Retourne 0 (succès) si pas de bug, 1 si bug présent
python -c "
from app import obtenir_statistiques
from app import TACHES
TACHES.clear()
try:
stats = obtenir_statistiques()
if stats['total'] == 0:
exit(0)
else:
exit(1)
except ZeroDivisionError:
exit(1)
"
chmod +x test_bug.sh

# Laisser Git faire le bisect automatiquement !
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
git bisect run ./test_bug.sh

# Git exécute le script sur chaque commit et trouve le coupable automatiquement
# À la fin :
git bisect reset

Log et replay de bisect

# Sauvegarder une session bisect pour plus tard
git bisect log > session-bisect.log

# Rejouer une session sauvegardée
git bisect replay session-bisect.log

git reflog — Le filet de sécurité

git reflog enregistre chaque mouvement de HEAD dans votre dépôt — c'est votre filet de sécurité ultime :

# Voir le reflog
git reflog

# Sortie :
# d5a1b4c HEAD@{0}: commit: feat: ajout statistiques
# c2e8f3a HEAD@{1}: checkout: moving from feature to main
# b7c9d1e HEAD@{2}: reset: moving to HEAD~1
# a3f4b2c HEAD@{3}: commit: feat: ajout recherche

Récupérer des commits « perdus »

# Vous avez accidentellement lancé git reset --hard et perdu des commits
git reset --hard HEAD~5 # Oups !

# Trouver les commits perdus dans le reflog
git reflog
# HEAD@{2} était avant le reset

# Récupérer
git reset --hard HEAD@{2}

# Ou créer une nouvelle branche depuis l'état perdu
git switch -c branche-recuperee HEAD@{2}
Reflog reste local

Le reflog n'est pas poussé vers GitHub. C'est un filet de sécurité local uniquement. Les entrées de reflog sont conservées 90 jours par défaut.


Résumé

CommandeDescription
git cherry-pick <hash>Appliquer un commit spécifique
git cherry-pick --continueContinuer après un conflit
git cherry-pick --abortAnnuler le cherry-pick
git bisect startDémarrer la recherche binaire
git bisect good/badMarquer un commit comme bon/mauvais
git bisect run <script>Bisect automatisé
git bisect resetTerminer la session bisect
git reflogVoir tous les mouvements de HEAD

Prochaines étapes