Débuter avec Git partie 6 : une fusion de branches échoue

Aujourd’hui pour continuer cette série d’articles sur débuter avec Git, nous allons démystifier une situation qui provoque un stress important auprès des nouveaux utilisateurs de Git : lorsqu’une fusion de branches échoue.

Il arrive malheureusement qu’une fusion de branches échoue. Ce cas se présente surtout dans l’utilisation collaborative de Git, où différentes personnes interviennent en même temps sur le code.

En effet Git est un outil très bien conçu, mais il ne prendra jamais une décision à la place de ses utilisateurs. Or, si la même partie du code est modifiée par deux utilisateurs différents, qui a raison ? Qui a tort ? Qui Git doit-il croire ?

Mise en place du conflit de fusion

Nous allons tout d’abord créer un fichier README.md dans un nouveau dépôt Git avec un titre et deux sections.

$ mkdir fusion-echoue
$ cd fusion-echoue/
$ git init .
Initialized empty Git repository in /tmp/fusion-echoue/.git/
$ vi README.md
$ cat README.md
# README

## installation

apt-get install whatever

## use

whatever param1 param3 param3
$ git add README.md && git commit README.md -m "add README.md"
add README.md
 1 file changed, 9 insertions(+)
 create mode 100644 README.md

Nous créons maintenant une branche dédiée à l’ajout d’une nouvelle section pour indiquer la licence du projet dans le README.md.

$ git checkout -b new-license
Switched to a new branch 'new-license'
$ vi README.md 
$ git commit README.md -m "license section"
license section
 1 file changed, 3 insertions(+)

Jetons un oeil à l’état actuel de notre fichier sur a branche new-license:

# README

## installation

apt-get install whatever

## use

whatever param1 param3 param3

# license
BSD

Un code, deux choix différents

Pendant ce temps, dans la branche master, un développeur semble avoir fait un choix différent au niveau de la licence.

git checkout master
Switched to branch 'master'
$ vi README.md 
$ git commit README.md -m "license section - use gpl"
[master bf15ff3] license section - use gpl
 1 file changed, 3 insertions(+)

Voici l’état actuel du fichier sur la branche master.

# README

## installation

apt-get install whatever

## use

whatever param1 param3 param3

# license
GPLv3

Une fusion destinée à échouer

L’événement-déclencheur du drame va être la volonté de supprimer la branche créée auparavant et de réintégrer son code dans master. Pour cela, rien de plus simple, nous utilisons git merge comme vu dans l’article précédent.

$ git merge new-license 
 Auto-merging README.md
 CONFLICT (content): Merge conflict in README.md
 Automatic merge failed; fix conflicts and then commit the result.

Oups, le CONFLICT en majuscule nous annonce que Git a rencontré un conflit en tentant de fusionner la branche new-license dans la branche master.

La dernière phrase est très claire : résoudre les conflits est un préalable indispensable à continuer la fusion.

Résoudre le conflit… ou pas

Si vous avez déjà rencontré ce problème en utilisant Git, vous avez sûrement éprouvé ce sentiment : la grosse panique. Vous vous voyez déjà accuser des pires manipulations par vos collègues et de casser l’outil de travail commun. DU CALME, PAS DU TOUT.

Avant de céder à la panique, repassons la commande git status.

$ 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 …" to mark resolution)
both modified:   README.md

La sortie de la commande est très claire : un simple git merge –abort vous fera revenir à la situation précédant le git merge. Voyons cela.

$ git merge --abort
$ git status
On branch master
nothing to commit, working tree clean

Voilà, vous pouvez vous détendre et ranger votre lette de démission. Tout va bien se passer.

Résouder le conflit

Nous allons maintenant tenter de réellement résoudre notre conflit. Avant cela, nous devons prendre conscience de la tâche qui nous attend.

$ git merge new-license
$ 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 …" to mark resolution)
both modified:   README.md

La sortie de la commande git status nous indique qu’un seul fichier pose problème par la mention sur la dernière ligne both modified: README.md.

Ce n’est pas nos quelques lignes dans le README.md qui vont nous décourager. Jetons donc un oeil au fichier en question.

$ cat README.md 
# README

## installation

apt-get install whatever

## use

whatever param1 param2 param3

## license
<<<<<<< HEAD
GPLv3
=======
BSD
>>>>>>> new-license                                                                                               

Surprise, Git nous a maché le travail.

Dans la section license du fichier, nous voyons que la partie entre <<<<<<< HEAD et ======= provient de HEAD, qui pointe actuellement sur master, donc le code provenant de master. Vous avez oublié ce qu’est HEAD ? On en parle dans cet article.

À l’opposé, la partie entre ======= et >>>>>>> new-license provient donc de la branche new-license. C’est maintenant à vous de jouer et de faire un choix, Git ne le fera pas à votre place, une décision humaine est attendue.

Après consultation avec vos collègues, vous choisissez la licence GPLv3. Vous allez donc éditer le code de la section license pour ne laisser que la partie suivante :

## license
GPLv3

La commande git status précédente nous indiquait la marche à suivre une fois le fichier édité.

Unmerged paths:
   (use "git add …" to mark resolution)
 both modified:   README.md

Nous suivons donc ces instructions à la lettre.

$ git add README.md 
$ git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Le conflit est résolu. Nous allons maintenant utiliser git commit pour terminer la fusion.

$ git commit -a -m "use GPLv3 license. merge from new-license branch"

Si vous n’utilisez que la commande git commit sans argument, votre éditeur de texte s’ouvre et propose d’enregistrer le message de commit suivant :

Merge branch 'new-license'

Conclusion

Nous avons brilliamment résolu notre premier conflit de fusion entre deux branches. Il était franchement facile à régler, mais il nous a permis de détailler toutes les étapes nécessaires. Bien évidemment nous pouvons avoir des conflits bien plus sévères à régler, mais nous avons vu comment interrompre une fusion, ce qui nous aidera quoiqu’il arrive à revenir à un état stable du dépôt.

S’engager dans une fusion complexe réclame un très bonne connaissance du code manipulé et de ce qu’on fait vos collègues, pour ne pas écraser du code utile par inadvertance.

Me suivre sur les réseaux sociaux

N’hésitez pas à me suivre directement sur les différents sociaux pour suivre au jour le jour mes différentes projets dans le Logiciel Libre :

Suivre l’actualité du Logiciel Libre et Open Source francophone

Abonnez-vous au Courrier du hacker, une newsletter hebdomadaire résumant le meilleur de l’actualité francophone du Logiciel Libre et Open Source. Déjà plus de 90 numéros et 2000 abonnés.

Le Courrier du hacker

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *