Guide détaillé, étape par étape
Le TD écrit deux versions différentes de la saisie d’une opération
dans src/main.py, sur deux branches, puis fusionne les deux
branches dans develop. Les deux versions modifient les
mêmes lignes : la seconde fusion s’arrête sur un conflit, que l’on
résout. Le TD correspond aux questions 21 à 25 de la feuille, et dure
environ vingt-cinq minutes.
On travaille dans le dépôt du TD 2a, tel que le TD 2c l’a laissé,
~/Desktop/info01/cours2/2a_premier_depot/travail/projet_2,
dans Git Bash. Les deux versions sont fournies dans le dossier du TD
:
2d_conflits\
├── depart\
│ ├── main_regex.py la saisie lue avec une expression régulière
│ └── main_operations.py la saisie découpée à la main
├── README.md
└── td_2d_conflits.pdf
| Étape | Objectif | Questions | Ce qu’on fait |
|---|---|---|---|
| 1 | modifier un fichier sur une branche | 21 | la première version, sur main_code |
| 2 | modifier la même ligne sur une autre branche | 22 et 23 | la seconde version, sur une nouvelle branche
main_code_bis |
| 3 | fusionner deux modifications de la même ligne | 24 | fusionner les deux branches dans develop : le
conflit |
| 4 | résoudre un conflit, puis terminer la fusion | 25 | résoudre le conflit, et terminer la fusion |
Chaque étape commence par un encadré qui la résume. Ce que chaque étape fait constater est expliqué à la fin du guide, dans « Ce que le TD fait constater » : faire l’étape d’abord, et noter ce qu’on observe, avant de lire l’explication.
main_codeÀ faire : sur
main_code, remplacer le contenu desrc/main.pypar celui dedepart/main_regex.py; faire un commit ; ne pas le fusionner.À obtenir : un commit
lecture de l'opération avec une regexsurmain_code.
cd ~/Desktop/info01/cours2/2a_premier_depot/travail/projet_2
git checkout main_code
cp ../../../2d_conflits/depart/main_regex.py src/main.py
git status
cp remplace src/main.py par le fichier
fourni, qui reprend le titre de la question 11 et y ajoute la saisie. Le
commentaire ajouté au TD 2c disparaît du fichier ; il reste dans
l’historique. git status liste src/main.py
comme modifié.
git add src/main.py
git commit -m "lecture de l'opération avec une regex"
La nouvelle version lit une ligne tapée au clavier, y cherche une
opération entre deux nombres avec une expression régulière, puis appelle
les fonctions de operations.py. Pour l’essayer :
python src/main.py, puis taper 12-5 et Entrée
; le programme affiche 7.0.
main_code_bisÀ faire : revenir sur
develop; y créermain_code_bis; remplacersrc/main.pypardepart/main_operations.py; faire un commit.À obtenir : un commit
lecture de l'opération par découpagesurmain_code_bis.
git checkout develop
git checkout -b main_code_bis
À noter : ce que contient src/main.py
sur cette branche, et si la version de l’étape 1 y est.
cp ../../../2d_conflits/depart/main_operations.py src/main.py
git add src/main.py
git commit -m "lecture de l'opération par découpage"
Cette version fait le même travail autrement : elle découpe la ligne tapée autour du signe de l’opération, et vérifie que les deux morceaux sont des nombres.
À faire : revenir sur
develop; y fusionnermain_code_bis, puismain_code.À obtenir : le second merge s’arrête sur un conflit dans
src/main.py.
git checkout develop
git merge main_code_bis
Le premier merge passe, en avance rapide
(Fast-forward).
git merge main_code
Fusion automatique de src/main.py
CONFLIT (contenu) : Conflit de fusion dans src/main.py
La fusion automatique a échoué ; réglez les conflits et validez le résultat.
git status
Sur la branche develop
Vous avez des chemins non fusionnés.
(réglez les conflits puis lancez "git commit")
(utilisez "git merge --abort" pour annuler la fusion)
Chemins non fusionnés :
(utilisez "git add <fichier>..." pour marquer comme résolu)
modifié des deux côtés : src/main.py
L’invite de Git Bash se termine maintenant par
(develop|MERGING) : la fusion est en cours.
À faire : ouvrir
src/main.py; pour chaque conflit, choisir la version à garder et supprimer les marqueurs ; vérifier que le programme se lance ; marquer le fichier comme résolu ; terminer la fusion.À obtenir : un commit
Merge branch 'main_code' into develop, et un programme qui calcule.
Ouvrir src/main.py dans VS Code. Le fichier contient
deux conflits : le début du fichier, où les deux versions ont un texte
d’introduction et des import différents, et la boucle de
saisie. Chacun a la forme suivante :
<<<<<<< HEAD
(la version de develop, venue de main_code_bis)
=======
(la version de main_code, qui arrive)
>>>>>>> main_code
À noter : ce qui se passe si l’on lance
python src/main.py à ce moment.
Pour chaque conflit, garder l’une des deux versions : celle qui est
entre <<<<<<< HEAD et
=======, ou celle qui est entre ======= et
>>>>>>> main_code. Supprimer l’autre,
puis les trois lignes de marqueurs. Garder la même version dans les deux
conflits : les import du début doivent correspondre au code
de la boucle, qui appelle add(…) dans la version de
main_code et op.add(…) dans celle de
main_code_bis.
VS Code affiche au-dessus de chaque conflit des liens cliquables :
Accept Current Change garde la version de HEAD, Accept
Incoming Change celle qui arrive, et chacun supprime les marqueurs du
conflit.
Enregistrer, puis vérifier que le fichier ne contient plus de marqueur et que le programme calcule :
grep -n "<<<<<<<\|=======\|>>>>>>>" src/main.py
python src/main.py
Vérification : grep n’affiche rien ; le
programme affiche son titre, attend une opération, et affiche
7.0 pour 12-5.
git add src/main.py
git merge --continue
Git ouvre l’éditeur avec le message
Merge branch 'main_code' into develop : Échap,
:wq, Entrée.
git llog
Vérification : le graphe commence ainsi :
* 4ced033 (HEAD -> develop) Merge branch 'main_code' into develop
|\
| * 6745df8 (main_code) lecture de l'opération avec une regex
| * 29a4b05 commentaire en tête de main.py
* | 4d853e1 (main_code_bis) lecture de l'opération par découpage
|/
* 06b3d3b Revert "suppression du code"
Cette section se lit après avoir fait les étapes.
Sur main_code_bis, créée depuis develop,
src/main.py ne contient que le titre de la question 11 : la
version de l’étape 1 est sur main_code, et n’a pas été
fusionnée. Les deux versions sont écrites à partir du même état du
fichier, comme le feraient deux personnes qui travaillent en même
temps.
Le premier merge est une avance rapide : develop n’avait
pas avancé depuis la création de main_code_bis. Le second
doit réunir deux modifications du même fichier, faites à partir du même
état. Git réunit seul des modifications qui portent sur des lignes
différentes. Ici, les deux branches ont remplacé les mêmes lignes, de
deux façons différentes : git ne peut pas choisir, et le merge s’arrête.
Il écrit alors les deux versions dans le fichier, à chaque endroit où
elles diffèrent, et la fusion reste en cours jusqu’à ce que la personne
qui fusionne ait choisi.
Lancé avec les marqueurs, le programme s’arrête sur une erreur :
<<<<<<< HEAD
^
SyntaxError: invalid syntax
Les lignes <<<<<<<,
======= et >>>>>>> sont
écrites dans le fichier comme n’importe quel texte. Git ne vérifie pas
qu’elles ont disparu : git add marque le fichier comme
résolu même s’il en contient encore. Un fichier Python qui en contient
ne s’exécute plus. Oublier d’en supprimer une est l’erreur la plus
fréquente du TD ; grep les retrouve.
La version gardée n’est pas imposée : on peut garder l’une, l’autre,
ou écrire une version qui combine les deux. Le commit de fusion
enregistre ce que contient le fichier au moment de git add,
et c’est ce contenu que develop porte ensuite. Tant que la
fusion n’est pas terminée, git merge --abort remet
develop dans l’état d’avant le merge.