Aller au contenu
English

Appliquer un correctif avec cherry-pick

  • Leçon 14
  • 45 min
  • Module 5 : Mises en production et correctifs urgents

Ce que vous saurez faire

Corrigez un bogue dans une version publiée sans publier du travail inachevé. Vous copiez un commit (enregistrement de changements) de main vers la branche de version. Vous pouvez prouver que rien d’autre ne l’accompagne.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 45 minutes

Ce que vous devez savoir

Ce qu’il vous faut sur votre ordinateur

Le centre d’assistance utilise la version 1.0. Il appelle l’équipe réseau au poste 4410, mais personne ne répond. Le bon poste est le 4401.

Sam a déjà corrigé ce problème sur main. Mais main contient deux autres nouveaux commits depuis la publication :

Commit Message Peut-il faire partie d’un correctif pour la version 1.0?
3cf73f7 Commencer l’exportation des billets (inachevée) Non. Le travail n’est pas terminé.
aeeb4b6 Corriger le poste de l’équipe réseau Oui. C’est le correctif.
3f4d833 Ajouter le billet 105 Non. C’est du nouveau contenu, pas un correctif.

Si l’équipe fusionne main dans release/1.0, les trois commits entrent dans la version. Le centre d’assistance reçoit alors une exportation inachevée. L’équipe a seulement besoin de aeeb4b6.

Un correctif urgent (hotfix) corrige une version que des gens utilisent déjà. L’équipe le publie comme une version PATCH (corrective), ici v1.0.1.

Cherry-pick (copie sélective) copie le changement d’un commit sur votre branche actuelle, sous forme d’un nouveau commit. Git lit le diff (les différences) du commit choisi et l’applique à votre branche. Le nouveau commit conserve le même message et le même auteur. Son identifiant de hachage est différent, car son parent est différent.

Deux lignes de commits. La ligne main : 465d7ea avec l'étiquette v1.0.0, puis 3cf73f7, l'exportation inachevée, puis aeeb4b6, le correctif, puis 3f4d833, le billet 105. La ligne release/1.0 commence à 465d7ea. Une flèche pointillée portant le texte cherry-pick -x descend de aeeb4b6 vers 19b64c1 sur release/1.0, la copie du correctif. Ensuite, 257b55a porte l'étiquette v1.0.1. Une flèche pointillée portant le texte merge back (fusion de retour) va de 257b55a vers un futur commit sur main.
cherry-pick -x copie seulement le correctif dans release/1.0. L'exportation inachevée reste sur main. Le chemin de la fusion de retour est le sujet de la prochaine leçon.

Le correctif et sa copie ont la même couleur, car ils contiennent le même changement. Ce sont des commits distincts, avec des identifiants de hachage différents.

Chaque étape se déroule sur une branche connue. Vérifiez la branche avant chaque commande.

Étape Branche actuelle Source → cible de la demande de tirage
1. Trouver et examiner le correctif release/1.0 aucune
2. Créer la branche du correctif urgent release/1.0 → hotfix/1.0.1 aucune
3. Copier avec cherry-pick, vérifier, pousser hotfix/1.0.1 aucune
4. Ouvrir et réviser la demande de tirage hotfix/1.0.1 hotfix/1.0.1 → release/1.0
5. Fusionner, étiqueter, pousser release/1.0 hotfix/1.0.1 → release/1.0 (fusionnée)

Le correctif entre dans la version par une demande de tirage, comme les autres changements. La cible est release/1.0, pas main.

  1. Exécutez le script de préparation avec le scénario hotfix :

    Terminal
    cd ~/projects
    sh nextia-learning-labs/C14/setup.sh hotfix --reset
    cd c14-lab/ticket-notes

    La sortie commence par Ready: (prêt).

  2. Consultez toutes les références :

    Terminal
    git log --oneline --graph --all --decorate -5
    Sortie
    * 3f4d833 (HEAD -> main, origin/main, origin/HEAD) Add ticket 105
    * aeeb4b6 Fix the network team extension
    * 3cf73f7 Start the ticket export (not finished)
    * 465d7ea (tag: v1.0.0, origin/release/1.0) Add escalation rules
    * f330fdc Add ticket 104

    Vous avez la branche distante origin/release/1.0, mais pas encore de branche locale release/1.0.

Branche actuelle : main. Amira passe à release/1.0. Git crée une branche locale qui suit origin/release/1.0 :

Terminal
git switch release/1.0
Sortie
Switched to a new branch 'release/1.0'
branch 'release/1.0' set up to track 'origin/release/1.0'.

Branche actuelle : release/1.0. Elle liste les commits présents sur main, mais absents de release/1.0. A..B signifie « les commits dans B qui ne sont pas dans A » :

Terminal
git log --oneline release/1.0..main
Sortie
3f4d833 Add ticket 105
aeeb4b6 Fix the network team extension
3cf73f7 Start the ticket export (not finished)

Le message d’un commit décrit le changement, mais le diff est le changement lui-même. Amira lit le diff avant de le copier :

Terminal
git show aeeb4b6
Sortie
commit aeeb4b6389efc1d6d75e474e911499fc5fe73e12
Author: Sam Okafor <sam@example.com>
Date: Tue Oct 6 09:12:00 2026 -0400
Fix the network team extension
diff --git a/contacts.txt b/contacts.txt
index 0ce0116..48d016f 100644
--- a/contacts.txt
+++ b/contacts.txt
@@ -1,3 +1,3 @@
Help desk: ext. 4100
Network team: ext. 4410
Network team: ext. 4401
Accounts team: ext. 4300

Le commit modifie une ligne dans un seul fichier. Il fait ce que le message annonce.

Un correctif dépend d’un commit précédent quand il modifie des lignes ajoutées par ce commit. Si ce commit précédent est absent de la version, le correctif ne peut pas s’y appliquer. Amira se pose deux questions.

La version contient-elle les lignes que le correctif modifie? Elle affiche contacts.txt tel qu’il est sur release/1.0 :

Terminal
git show release/1.0:contacts.txt
Sortie
Help desk: ext. 4100
Network team: ext. 4410
Accounts team: ext. 4300

La version contient la ligne Network team: ext. 4410 (équipe réseau : poste 4410), identique à celle que le correctif supprime. Le correctif peut donc s’appliquer.

Le correctif a-t-il besoin d’un autre commit de main? Le seul commit entre la version et le correctif est celui de l’exportation. --stat affiche les fichiers qu’il a modifiés :

Terminal
git show --stat 3cf73f7
Sortie (fin)
Start the ticket export (not finished)
export.txt | 2 ++
1 file changed, 2 insertions(+)

L’exportation a seulement modifié export.txt. Le correctif a seulement modifié contacts.txt. Le correctif n’a pas besoin de l’exportation.

4. Créer la branche du correctif urgent à partir de la version

Section intitulée « 4. Créer la branche du correctif urgent à partir de la version »

Branche actuelle : release/1.0. Amira crée la branche du correctif urgent ici, pas sur main. Une branche part du commit où vous vous trouvez, et le correctif doit aller dans la version :

Terminal
git switch -c hotfix/1.0.1
Sortie
Switched to a new branch 'hotfix/1.0.1'

Branche actuelle : hotfix/1.0.1. L’option -x ajoute une ligne au message du nouveau commit. Cette ligne indique le commit d’origine pour que chacun puisse retrouver la source de la copie.

Terminal
git cherry-pick -x aeeb4b6
Sortie
[hotfix/1.0.1 19b64c1] Fix the network team extension
Author: Sam Okafor <sam@example.com>
Date: Tue Oct 6 09:12:00 2026 -0400
1 file changed, 1 insertion(+), 1 deletion(-)

Le nouveau commit est 19b64c1. Votre identifiant de hachage est différent, car vous avez fait la copie à un autre moment. Git a gardé Sam comme auteur, car il a écrit le changement. Le message complet montre la ligne ajoutée par -x :

Terminal
git log -1
Sortie
commit 19b64c13a2bb62fa029d4884fc18af8816ff3f1d
Author: Sam Okafor <sam@example.com>
Date: Tue Oct 6 09:12:00 2026 -0400
Fix the network team extension
(cherry picked from commit aeeb4b6389efc1d6d75e474e911499fc5fe73e12)

Le graphe montre maintenant la copie sur sa propre ligne, à partir de v1.0.0 :

Terminal
git log --oneline --graph --all --decorate -6
Sortie
* 19b64c1 (HEAD -> hotfix/1.0.1) Fix the network team extension
| * 3f4d833 (origin/main, origin/HEAD, main) Add ticket 105
| * aeeb4b6 Fix the network team extension
| * 3cf73f7 Start the ticket export (not finished)
|/
* 465d7ea (tag: v1.0.0, origin/release/1.0, release/1.0) Add escalation rules
* f330fdc Add ticket 104

Branche actuelle : hotfix/1.0.1. Amira lance la vérification, puis pousse la branche :

Terminal
sh check.sh
git push -u origin hotfix/1.0.1
Sortie
PASS: 4 ticket lines checked
To /Users/amira/projects/c14-lab/team-remote.git
* [new branch] hotfix/1.0.1 -> hotfix/1.0.1
branch 'hotfix/1.0.1' set up to track 'origin/hotfix/1.0.1'.

Demande de tirage : source hotfix/1.0.1 → cible release/1.0. C’est une demande de tirage simulée, comme dans le module 3. Sam, qui fait la révision, vérifie le diff que la demande de tirage ajoute à la version :

Terminal
git diff release/1.0...hotfix/1.0.1
Sortie
diff --git a/contacts.txt b/contacts.txt
index 0ce0116..48d016f 100644
--- a/contacts.txt
+++ b/contacts.txt
@@ -1,3 +1,3 @@
Help desk: ext. 4100
-Network team: ext. 4410
+Network team: ext. 4401
Accounts team: ext. 4300

Le diff contient une ligne modifiée. Aucune exportation, aucun billet 105. Sam approuve.

Branche actuelle : release/1.0. Amira passe à la cible de la demande de tirage et la fusionne :

Terminal
git switch release/1.0
git merge --no-ff --no-edit hotfix/1.0.1
Sortie (fin)
Merge made by the 'ort' strategy.
contacts.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Branche actuelle : release/1.0. Elle étiquette la version, puis pousse la branche et l’étiquette :

Terminal
git tag -a v1.0.1 -m "Help desk notes 1.0.1"
git push
git push origin v1.0.1
Sortie
To /Users/amira/projects/c14-lab/team-remote.git
465d7ea..257b55a release/1.0 -> release/1.0
To /Users/amira/projects/c14-lab/team-remote.git
* [new tag] v1.0.1 -> v1.0.1

Amira prouve que la version 1.0.1 contient le correctif, et rien d’autre. D’abord, les fichiers modifiés entre les deux versions :

Terminal
git diff v1.0.0 v1.0.1 --stat
Sortie
contacts.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Ensuite, les commits présents dans 1.0.1, mais absents de 1.0.0 :

Terminal
git log --oneline v1.0.0..v1.0.1
Sortie
257b55a Merge branch 'hotfix/1.0.1' into release/1.0
19b64c1 Fix the network team extension

Enfin, l’exportation inachevée est absente de la version :

Terminal
git show v1.0.1:export.txt
Sortie
fatal: path 'export.txt' does not exist in 'v1.0.1'

Cette erreur est le résultat qu’elle souhaite. Le graphe complet correspond maintenant au schéma du début de la leçon :

git log --oneline --graph --all --decorate -8
* 257b55a (HEAD -> release/1.0, tag: v1.0.1, origin/release/1.0) Merge branch 'hotfix/1.0.1' into release/1.0
|\
| * 19b64c1 (origin/hotfix/1.0.1, hotfix/1.0.1) Fix the network team extension
|/
| * 3f4d833 (origin/main, origin/HEAD, main) Add ticket 105
| * aeeb4b6 Fix the network team extension
| * 3cf73f7 Start the ticket export (not finished)
|/
* 465d7ea (tag: v1.0.0) Add escalation rules
* f330fdc Add ticket 104
* e058b3f Add ticket 103
  1. Exécutez la préparation de Préparer l’état d’exercice. Vous êtes sur main dans ticket-notes.

  2. Passez à la branche de version :

    Terminal
    git switch release/1.0

    Branche actuelle : release/1.0. La sortie contient set up to track 'origin/release/1.0' (configurée pour suivre « origin/release/1.0 »).

  3. Exécutez git log --oneline release/1.0..main. La sortie liste trois commits. Notez l’identifiant de hachage de Fix the network team extension (corriger le poste de l’équipe réseau).

  4. Exécutez git show aeeb4b6. Vérifiez qu’il modifie seulement la ligne de l’équipe réseau dans contacts.txt.

  5. Exécutez git show release/1.0:contacts.txt. Vérifiez que la version contient Network team: ext. 4410.

  6. Créez la branche du correctif urgent à partir de la version :

    Terminal
    git switch -c hotfix/1.0.1

    Branche actuelle : hotfix/1.0.1.

  7. Copiez le correctif :

    Terminal
    git cherry-pick -x aeeb4b6

    La sortie commence par [hotfix/1.0.1 et un nouvel identifiant de hachage.

  8. Exécutez git log -1. Le message se termine par (cherry picked from commit aeeb4b6...) (copié depuis le commit aeeb4b6…).

  9. Exécutez sh check.sh. La sortie commence par PASS (réussite).

  10. Poussez la branche du correctif urgent :

    Terminal
    git push -u origin hotfix/1.0.1
  11. Révisez la demande de tirage simulée, source hotfix/1.0.1 → cible release/1.0 :

    Terminal
    git diff release/1.0...hotfix/1.0.1

    Le diff montre une ligne modifiée dans contacts.txt, et rien d’autre.

  12. Passez à la branche cible et fusionnez :

    Terminal
    git switch release/1.0
    git merge --no-ff --no-edit hotfix/1.0.1

    Branche actuelle : release/1.0. La sortie contient Merge made by the 'ort' strategy. (fusion effectuée avec la stratégie « ort »).

  13. Étiquetez la version :

    Terminal
    git tag -a v1.0.1 -m "Help desk notes 1.0.1"
  14. Poussez la branche, puis l’étiquette :

    Terminal
    git push
    git push origin v1.0.1
  15. Exécutez git diff v1.0.0 v1.0.1 --stat. La sortie liste seulement contacts.txt.

  16. Exécutez git show v1.0.1:export.txt. La sortie est fatal: path 'export.txt' does not exist in 'v1.0.1' (erreur fatale : le chemin « export.txt » n’existe pas dans « v1.0.1 »).

Sam trouve un deuxième bogue : le poste de l’équipe de comptabilité est 4310, et non 4300. Vous jouez les deux rôles. Partez de la fin de l’exercice guidé.

  1. Dans le rôle de Sam, dans sam-notes, corrigez la ligne de contacts.txt sur main. Créez un commit (enregistrement des modifications) avec le message Fix the accounts team extension (corriger le poste de l’équipe de comptabilité), puis poussez-le.
  2. Dans le rôle d’Amira, dans ticket-notes, publiez la correction dans la version 1.0.2.
  3. Pour chaque étape, indiquez la branche courante et, s’il y a une demande de tirage, ses branches source et cible.

Deux règles s’appliquent. Add ticket 105 (ajouter le billet 105) ajoute du contenu; ce n’est pas une correction. Il ne doit donc pas faire partie de la version. La version ne doit pas contenir export.txt.

Afficher une réponse modèle
Étape Où Branche courante Source → cible de la demande de tirage
Sam tire, corrige, crée un commit et pousse sam-notes main aucune (dans une vraie équipe : fix-accounts → main)
Amira tire la correction ticket-notes main aucune
Trouver et examiner la correction ticket-notes main aucune
Créer la branche de correction urgente ticket-notes release/1.0 → hotfix/1.0.2 aucune
Copier le commit par cherry-pick, vérifier et pousser ticket-notes hotfix/1.0.2 aucune
Réviser ticket-notes hotfix/1.0.2 hotfix/1.0.2 → release/1.0
Fusionner, créer l’étiquette v1.0.2 et pousser ticket-notes release/1.0 hotfix/1.0.2 → release/1.0 (fusionnée)

Dans le rôle de Sam, récupérez la dernière version de main. Dans votre éditeur, remplacez ensuite Accounts team: ext. 4300 (équipe de comptabilité : poste 4300) par Accounts team: ext. 4310 (équipe de comptabilité : poste 4310). Créez un commit et poussez-le :

Terminal (Sam)
cd ../sam-notes
git pull
git commit -am "Fix the accounts team extension"
git push

Dans le rôle d’Amira, trouvez la correction. git log affiche quatre commits, car la copie de la première correction a une empreinte différente de l’original de Sam. La prochaine leçon explique pourquoi.

Terminal
cd ../ticket-notes
git switch main
git pull
git log --oneline release/1.0..main
Output (git log only)
772b7bf Fix the accounts team extension
3f4d833 Add ticket 105
aeeb4b6 Fix the network team extension
3cf73f7 Start the ticket export (not finished)

Copiez seulement 772b7bf (votre empreinte sera différente). Vérifiez-le d’abord avec git show 772b7bf.

Terminal
git switch release/1.0
git switch -c hotfix/1.0.2
git cherry-pick -x 772b7bf
sh check.sh
git push -u origin hotfix/1.0.2
git diff release/1.0...hotfix/1.0.2
git switch release/1.0
git merge --no-ff --no-edit hotfix/1.0.2
git tag -a v1.0.2 -m "Help desk notes 1.0.2"
git push
git push origin v1.0.2

Prouvez le résultat :

Terminal
git diff v1.0.1 v1.0.2 --stat
git log --oneline v1.0.1..v1.0.2
Sortie
contacts.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
3a01c9f Merge branch 'hotfix/1.0.2' into release/1.0
9e8c739 Fix the accounts team extension

git show v1.0.2:tickets.txt se termine par le billet 104. Le billet 105 ne fait donc pas partie de la version.

Erreur courante

Le cherry-pick s'arrête à cause d'un conflit

Symptôme : Sam a modifié le texte du billet 105 sur main, dans un commit nommé Fix the wording of ticket 105 (corriger le texte du billet 105). Sur hotfix/1.0.1, vous essayez de le copier :

Terminal
git cherry-pick -x bd75493
Sortie (premières lignes)
Auto-merging tickets.txt
CONFLICT (content): Merge conflict in tickets.txt
error: could not apply bd75493... Fix the wording of ticket 105

git status affiche You are currently cherry-picking commit bd75493 (vous copiez actuellement le commit bd75493 par cherry-pick) et both modified: tickets.txt (modifié des deux côtés : tickets.txt).

Cause : le commit dépend d’un commit absent de la version. Il modifie la ligne du billet 105, qui provient de Add ticket 105. La version n’a pas cette ligne :

Terminal
git show release/1.0:tickets.txt
Sortie
Ticket 101: printer offline. Restarted the spooler.
Ticket 102: password reset email not received.
Ticket 103: shared drive is slow. Moved the user to the new server.
Ticket 104: laptop will not charge. Replaced the power adapter.

Correction :

  1. Arrêtez le cherry-pick. Git remet la branche dans son état précédent :

    Terminal
    git cherry-pick --abort
    git status
    Sortie
    On branch hotfix/1.0.1
    nothing to commit, working tree clean
  2. Décidez avec votre équipe. Ici, la version n’a pas de billet 105, donc elle n’a pas besoin de cette correction. Ne copiez pas ce commit.

Si une vraie correction dépend d’un commit précédent, vous devez aussi copier ce commit ou réécrire la correction pour la version. Ne résolvez pas le conflit en ajoutant des lignes que la version n’a jamais eues. Exécutez toujours git show avant de copier un commit pour repérer d’abord la dépendance.

Erreur courante

J'ai copié le mauvais commit

Symptôme : vous avez copié 3cf73f7 au lieu de la correction, puis poussé la branche de correction urgente. La révision de la demande de tirage montre le mauvais fichier :

Terminal
git diff release/1.0...hotfix/1.0.1 --stat
Sortie
export.txt | 2 ++
1 file changed, 2 insertions(+)

Cause : les empreintes 3cf73f7 et aeeb4b6 se trouvent sur des lignes voisines dans git log. Il est facile de copier la mauvaise.

Correction : sur hotfix/1.0.1, avant de fusionner la demande de tirage :

  1. Annulez la mauvaise copie :

    Terminal
    git revert --no-edit HEAD
    Output (first line)
    [hotfix/1.0.1 38d6b6e] Revert "Start the ticket export (not finished)"
  2. Copiez le bon commit : git cherry-pick -x aeeb4b6.

  3. Révisez de nouveau les différences de la demande de tirage :

    Terminal
    git diff release/1.0...hotfix/1.0.1 --stat
    Sortie
    contacts.txt | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)
  4. Poussez et demandez une nouvelle révision.

Les différences sont maintenant correctes. L’historique de la branche de correction urgente montre encore l’erreur et son annulation. C’est honnête et sûr.

Vérifiez votre compréhension

Prédisez : vous copiez aeeb4b6 sur hotfix/1.0.1 par cherry-pick. Le nouveau commit a-t-il l'empreinte aeeb4b6? Après la fusion de la correction urgente, git log release/1.0..main affiche-t-il encore aeeb4b6?

Afficher la réponse

Non à la première question. La copie est un nouveau commit avec une nouvelle empreinte, car son parent est différent. Oui à la deuxième : release/1.0 contient la copie, et non aeeb4b6 lui-même. Donc, git log release/1.0..main affiche encore aeeb4b6. La ligne -x permet de retrouver l’original à partir de la copie.

Vérifiez votre compréhension

Vérification pratique : prouvez que v1.0.1 contient la correction, mais ne contient ni l'exportation inachevée ni le billet 105.

Afficher la réponse
  • git show v1.0.1:contacts.txt affiche Network team: ext. 4401 (équipe réseau : poste 4401).
  • git diff v1.0.0 v1.0.1 --stat affiche seulement contacts.txt.
  • git log --oneline v1.0.0..v1.0.1 affiche seulement la copie de la correction et le commit de fusion.
  • git show v1.0.1:export.txt échoue avec does not exist (n’existe pas), et git show v1.0.1:tickets.txt se termine par le billet 104.

Récapitulatif

  • Le cherry-pick copie les modifications d’un commit sur votre branche courante, dans un nouveau commit avec une nouvelle empreinte.
  • Utilisez git log --oneline release/1.0..main pour trouver la correction, puis git show pour la lire avant de la copier.
  • Vérifiez les dépendances : la version doit avoir les lignes que la correction modifie. La correction ne doit pas nécessiter d’autres commits de main.
  • Créez hotfix/1.0.1 à partir de release/1.0, copiez le commit avec -x, puis ouvrez une demande de tirage ciblant release/1.0.
  • Créez l’étiquette v1.0.1 sur le résultat fusionné, poussez l’étiquette et vérifiez la version avec git diff v1.0.0 v1.0.1 --stat.

Leçon suivante : Garder des historiques cohérents