Session 12 : Git Branches : des univers parallèles pour ton code

La session précédente, tu as appris à faire des commits : des photos de ton code sur une seule ligne du temps. Tout bien à la suite.

Mais si tu veux essayer une nouvelle idée ? Ajouter un pistolet laser à ton jeu, par exemple. Tu ne sais pas si ça va marcher. Tu ne veux pas casser ton code qui fonctionne.

C’est pour ça que les branches existent.

Une branche est une copie de ton code où tu peux expérimenter librement. Ton code principal (la branche master) reste en sécurité. Si ton expérience marche, tu la recolles dans master. Si elle ne marche pas ? Tu jettes la branche. Ta branche master n’en a jamais rien su.

Note : sur GitHub et dans beaucoup de nouveaux projets, la branche principale s’appelle main au lieu de master. C’est exactement la même chose, seul le nom change. Dans ce cours, on utilise master, mais si tu croises main en ligne, tu sais que ça veut dire la même chose.

Ce que tu vas apprendre aujourd’hui

  • Ce qu’est une branche et comment Git stocke les branches en interne
  • Créer, changer et fusionner des branches
  • Ce qu’est un merge conflict et comment le résoudre
  • Quand utiliser une branche, et quand pas

Étape 0 : Rappel : où en es-tu ?

Ouvre ton terminal dans le projet de la session précédente. Vérifie où tu es :

git status
git log --oneline

Tu as quelques commits sur master. C’est ta base stable : c’est d’ici que tu vas te séparer tout à l’heure.

Étape 1 : Ta première branche

Tu vas ajouter une nouvelle feature : un fichier highscore.txt qui garde le meilleur score. Mais d’abord, tu crées une branche :

git branch highscore-feature

Git a maintenant créé une nouvelle branche. Mais tu es toujours sur master. Vérifie quelles branches existent :

git branch

Tu vois :

  highscore-feature
* master

L’astérisque à côté de master veut dire : « tu es ici ». Passe à ta nouvelle branche :

git switch highscore-feature

(Les versions plus anciennes de Git utilisent git checkout highscore-feature. Les deux marchent.)

Encore une fois git branch : l’astérisque est maintenant à côté de highscore-feature. Tout ce que tu commites maintenant se passe sur cette branche. master reste intact.

Astuce : tu peux créer une branche et y aller directement en une seule commande :

git switch -c mijn-nieuwe-branch

-c veut dire « create ». C’est plus rapide et tu n’oublies jamais de changer de branche.

Étape 2 : Travailler sur une branche

Crée un nouveau fichier :

echo "HIGHSCORE: 0" > highscore.txt

Committe ton travail :

git add highscore.txt
git commit -m "Add highscore.txt avec valeur de départ 0"

Ajoute encore un fichier qui lit le highscore :

echo 'def lees_highscore():' > highscore_manager.py
echo '    with open("highscore.txt") as f:' >> highscore_manager.py
echo '        return int(f.read().split(": ")[1])' >> highscore_manager.py

Committe encore :

git add highscore_manager.py
git commit -m "Add highscore_manager : fonction pour lire le highscore"

Regarde maintenant ton log :

git log --oneline

Tu vois tous tes commits de master, plus les deux nouveaux. Git se souvient de toute la chaîne.

Étape 3 : Deux mondes en même temps

Reviens sur master :

git switch master

Regarde ce qu’il y a ici :

ls

highscore.txt et highscore_manager.py ont… disparu. Ils existent seulement sur la branche highscore-feature. Sur master, tout est encore exactement comme tu l’as laissé.

C’est la magie des branches : deux (ou plus) versions de ton projet, en même temps sur ton ordinateur, sans se gêner.

Change encore une fois dans les deux sens pour le sentir :

git switch highscore-feature   # les fichiers sont revenus
git switch master                # les fichiers ont encore disparu

Étape 4 : Fusionner avec git merge

Ta feature highscore fonctionne. Il est temps de la remettre dans master. Ça s’appelle merger.

Assure-toi d’être sur master :

git switch master

Fusionne la branche :

git merge highscore-feature

Git affiche quelque chose comme Updating a1b2c3d..e4f5g6h et Fast-forward. Tes commits de highscore-feature font maintenant partie de master. Vérifie :

ls
git log --oneline

highscore.txt et highscore_manager.py sont maintenant sur master. Tous les commits de la branche feature sont repris dans l’historique.

Étape 5 : C’est quoi, un merge conflict ?

Imagine : tu as changé quelque chose sur master dans highscore.txt, par exemple “HIGHSCORE: 100” au lieu de “HIGHSCORE: 0”. Et en même temps, sur une autre branche, tu as aussi changé highscore.txt, en “HIGHSCORE: 500”.

Si tu essaies de merger maintenant, Git ne sait pas quelle version est la bonne. C’est un merge conflict. Git te demande à toi de décider.

Provoquons-le exprès.

Sur master :

echo "HIGHSCORE: 100" > highscore.txt
git add highscore.txt
git commit -m "Update highscore à 100 sur master"

Crée une nouvelle branche et change le même fichier :

git switch -c andere-highscore
echo "HIGHSCORE: 500" > highscore.txt
git add highscore.txt
git commit -m "Update highscore à 500"

Reviens sur master et essaie de merger :

git switch master
git merge andere-highscore

Git dit : CONFLICT (content): Merge conflict in highscore.txt. Ouvre highscore.txt dans ton éditeur. Tu vois :

<<<<<<< HEAD
HIGHSCORE: 100
=======
HIGHSCORE: 500
>>>>>>> andere-highscore

Ce sont les deux versions. HEAD, c’est ta version master. En dessous se trouve la version de andere-highscore. Tu choisis laquelle tu gardes, ou tu les combines.

Supprime les marqueurs et choisis une version :

HIGHSCORE: 500

Enregistre le fichier. Dis à Git que le conflit est résolu :

git add highscore.txt
git commit -m "Merge : highscore de andere-highscore choisi"

Conflit résolu. Git peut continuer.

Étape 6 : Ranger les branches

Ta feature est mergée. Tu n’as plus besoin de la branche :

git branch -d highscore-feature
git branch -d andere-highscore

-d veut dire « delete ». Git refuse de supprimer une branche qui n’est pas encore mergée : c’est une soupape de sécurité. Si tu veux vraiment jeter une branche sans la merger, utilise -D (majuscule). Mais fais attention avec ça.

Une branche ou pas, quand ?

Une branche, ouiPas de branche
Une nouvelle feature qui prend du tempsCorriger une faute dans un commentaire
Une expérience dont tu ne sais pas si ça marcheUn petit bugfix d’une ligne
Quelque chose qui peut casser ton code qui marcheTu travailles seul et ta modification est claire
Tu travailles avec d’autres(en solo, master suffit souvent)

Règle de base : si tu hésites, fais une branche. Une branche ne coûte rien. Perdre du code, si.

Astuces pour travailler vite avec les branches

  1. Garde tes branches courtes. Une branche de 3 heures, c’est parfait. Une branche de 3 semaines devient un cauchemar de merge : plus tu attends pour merger, plus master change entre-temps, et plus le risque de conflicts augmente.
  2. Une seule chose par branche. « Ajouter le highscore » est une bonne branche. « Ajouter le highscore, un menu et de nouveaux niveaux » est trop : découpe-le.
  3. Merge souvent. Quand ta feature est finie, merge-la tout de suite dans master. Des merges petits et fréquents sont plus faciles qu’un seul gros merge monstre.
  4. Donne des noms clairs à tes branches. highscore-feature, c’est bien. test123 ou branch2, c’est mauvais. Dans une semaine, tu ne sauras plus ce qu’il y avait dans test123.
  5. Vérifie où tu es avant de commencer. git branch ou git status te dit sur quelle branche tu es. Fais-en une habitude, pour éviter d’écrire par accident du code sur master qui appartient en fait à une branche feature.

Showcase

Montre à un coach et à un buddy :

  1. git branch avec au moins deux branches (dont master).
  2. Sur chaque branche, un autre fichier ou d’autre code.
  3. Le switch dans les deux sens : les fichiers apparaissent et disparaissent.
  4. Un merge réussi d’une branche feature dans master.

À la prochaine !

« Jusqu’ici, tout ton code vit seulement sur ton laptop. La prochaine fois, on le met en ligne. Tu crées un compte GitHub, tu pushes ton dépôt sur internet, et ton jeu est visible partout dans le monde. Et : tu peux collaborer avec d’autres. GitHub : ton code dans le monde entier. »

À emporter chez toi

  1. Facile : crée une branche pour une petite feature dans un projet existant. Committe ton travail et merge-la.
  2. Moyen : crée exprès un merge conflict (deux branches qui modifient le même fichier) et résous-le.
  3. Difficile : travaille avec trois branches en même temps sur le même projet. Merge-les une par une dans master. Vérifie après chaque merge que tout marche encore.
  4. Très difficile : crée une branche, fais trois commits, reviens sur master, fais là aussi une modification dans le même fichier, et merge la branche. Résous le conflit soigneusement et vérifie avec git log --graph à quoi ressemble l’historique.