Voici le onzième volet de la formation Git. Dans mon précédent article, nous avons abordé la fusion de deux branches symbolisée par un merge commit. Malheureusement les choses ne se passent pas toujours comme prévu, et vous pouvez vous retrouver confronté à un conflit de fusion. Ce cas de figure intimide particulièrement les novices de Git. J’ai donc décidé d’en parler un peu plus en détail. Une fois que vous aurez intégré quelques principes de base, vous verrez que la résolution d’un conflit n’est pas de la magie noire.
Les conflits par la pratique
Pour illustrer ce qui se passe lorsque la fusion de deux branches résulte en un conflit, je vais reprendre mon exemple de l’atelier pratique sur la création des branches en le modifiant quelque peu. Commencez par initialiser un nouveau dépôt Git :
$ cd ~/formation-git/
$ mkdir atelier-16
$ cd atelier-16
$ git init
...
Initialized empty Git repository in /home/kikinovak/formation-git/atelier-15/.git/
Créez un fichier hello.sh
:
#!/bin/bash
#
# hello.sh
echo "Hello !"
Rendez le fichier exécutable :
$ chmod +x hello.sh
Ajoutez le fichier à l’index de Git et validez-le :
$ git add hello.sh $ git commit -m "Commit initial." [master (root-commit) bf79c2e] Commit initial. 1 file changed, 5 insertions(+) create mode 100755 hello.sh
Maintenant, créez deux branches hello-cow
et hello-figlet
:
$ git branch hello-cow $ git branch hello-figlet
Positionnez-vous sur la branche hello-cow
:
$ git switch hello-cow Switched to branch 'hello-cow'
Éditez le script hello.sh
comme ceci :
#!/bin/bash
#
# hello.sh
if [ -x /usr/bin/cowsay ]
then
cowsay "Hello !"
else
echo "Hello !"
fi
Enregistrez les modifications et validez-les :
$ git add hello.sh $ git commit -m "Message avec une vache qui parle." [hello-cow 0d4f1b9] Message avec une vache qui parle. 1 file changed, 6 insertions(+), 1 deletion(-)
Maintenant, basculez vers la branche hello-figlet
:
$ git switch hello-figlet Switched to branch 'hello-figlet'
Éditez le script hello.sh
pour qu’il ressemble à ceci :
#!/bin/bash
#
# hello.sh
if [ -x /usr/bin/figlet ]
then
figlet "Hello !"
else
echo "Hello !"
fi
Enregistrez les modifications et validez-les :
$ git add hello.sh $ git commit -m "Message en lettres ASCII." [hello-figlet ef91dab] Message en lettres ASCII. 1 file changed, 6 insertions(+), 1 deletion(-)
Puis, revenez sur la branche master
:
$ git switch master Switched to branch 'master'
Le moment est venu de fusionner toutes ces branches :
$ git branch
hello-cow
hello-figlet
* master
Avant d’aller plus loin, prenez un moment pour réfléchir à ce qui va se passer. Visualisez l’historique de vos commits et demandez-vous à quoi pourra bien ressembler une fusion de toutes ces branches.
Commençons par intégrer la branche hello-cow
:
$ git merge hello-cow Updating bf79c2e..0d4f1b9 Fast-forward hello.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
Notez bien qu’il s’agit d’un fast-forward merge, étant donné que la branche master
n’a pas été modifiée depuis la création de la branche hello-cow
.
Voici à quoi ressemble mon script hello.sh
à présent :
#!/bin/bash
#
# hello.sh
if [ -x /usr/bin/cowsay ]
then
cowsay "Hello !"
else
echo "Hello !"
fi
Là aussi, réfléchissez et essayez d’anticiper ce qui va se passer pour la suite. Puis lancez-vous et tentez de fusionner la branche hello-figlet
:
$ git merge hello-figlet
Auto-merging hello.sh
CONFLICT (content): Merge conflict in hello.sh
Automatic merge failed; fix conflicts and then commit the result.
Argh. Le message d’erreur CONFLICT
a l’air passablement intimidant. Essayons d’en savoir un peu plus :
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: hello.sh
no changes added to commit (use "git add" and/or "git commit -a")
Git fait de son mieux pour nous aider ici, si nous suivons ses suggestions. Ouvrons donc le fichier hello.sh
avec notre éditeur de texte préféré et voyons à quoi il ressemble :
#!/bin/bash # # hello.sh <<<<<<< HEAD if [ -x /usr/bin/cowsay ] then cowsay "Hello !" ======= if [ -x /usr/bin/figlet ] then figlet "Hello !" >>>>>>> hello-figlet else echo "Hello !" fi
Une belle pagaille ? Pas tant que ça en fait. Essayons de comprendre toutes ces annotations :
- La ligne qui commence par
<<<<<<<
marque le début de la zone conflictuelle. - Pour l’instant, retenez que
HEAD
symbolise la branche sur laquelle vous vous trouvez, en l’occurrencemaster
. - Le marqueur
=======
représente la frontière entre les deux zones à fusionner. - La ligne qui commence par
>>>>>>>
délimite la fin de la zone conflictuelle. hello-figlet
c’est la branche que nous souhaitons fusionner dans la brancheHEAD
, en l’occurrencemaster
.
À présent, c’est à vous d’éditer le fichier hello.sh
pour résoudre le conflit manuellement. En gros, vous avez quatre possibilités :
- Ignorer les changements introduits dans la branche
hello-figlet
. - Conserver les changements de la branche
hello-figlet
. - Tout garder et tenter de faire un mix des deux branches.
- Décider de faire complètement autre chose.
Vous commencez peut-être à comprendre pourquoi Linus Torvalds a appelé Git « the stupid content tracker » (man git
). Git n’essaie même pas de résoudre ce genre de conflit à votre place. Dès qu’il ne sait plus quoi faire, il vous rend la main et c’est à vous de décider ce qu’il faut faire.
Une fois que vous avez édité le fichier hello.sh
à votre convenance, enregistrez les modifications et ajoutez le résultat final à la zone d’indexation :
$ git add hello.sh
Si vous effectuez un commit, Git va lancer un éditeur de texte avec un message automatique :
Merge branch 'hello-figlet'
# Conflicts:
# hello.sh
#
# It looks like you may be committing a merge.
# If this is not correct, please run
# git update-ref -d MERGE_HEAD
# and try again.
Là aussi, vous pouvez conserver le message généré par Git. Enregistrez et quittez l’éditeur.
[master f44f55d] Merge branch 'hello-figlet'
Félicitations ! Vous venez de résoudre votre premier conflit de fusion avec Git.
Exercice
- Créez un répertoire
formation-git/atelier-17
et initialisez un dépôt Git dans ce répertoire. - Éditez un script
hello.sh
qui afficheHello world !
- Ajoutez le script à la branche
master
. - Créez deux branches
i-love-dogs
eti-love-cats
. - Basculez vers la branche
i-love-dogs
. - Éditez
hello.sh
pour qu’il afficheHello dogs !
- Enregistrez et validez.
- Basculez vers la branche
i-love-cats
. - Éditez
hello.sh
pour qu’il afficheHello cats !
- Enregistrez et validez.
- Revenez dans la branche
master
. - Fusionnez successivement les deux branches
i-love-dogs
eti-love-cats
. - Essayez de résoudre les conflits de fusion selon vos préférences.
Lire la suite : Afficher l’historique
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.
0 commentaire