Tuto Git – Modifications simultanées de fichiers avec conflit

Objectif: Ce « Tuto Git » traite de la gestion des conflits de modifications effectuées par deux ou plusieurs développeurs. Git considère qu’il y a conflit quand le contenu d’une même ligne est différent entre deux versions du même fichier (version locale et version distante sur le serveur qui heberge le dépôt de données). Une ligne dans un fichier est identifiée par son numéro comptabilisé du haut vers le bas du fichier. Pré-requis: Git est installé et configuré, les notions de base d’utilisation de git sont assimilées.

1. Configuration permanente de « pull –no-edit »

Dans l’article précédent on a utilisé la commande git pull –no-edit pour récupérer le contenu du/des fichier(s) modifié(s) sur le serveur. Le paramètre –no-edit permet d’éviter l’ouverture systématique (en cas de modifications en local et sur le serveur sans conflit) d’un éditeur de texte pour la saisie d’un commentaire. Si on souhaite garder ce mode de fonctionnement sans devoir à chaque fois utiliser ce paramètre, on doit le configurer. Pour cela il faudra executer la commande:
git config --global core.mergeoptions --no-edit

 2. Configuration de la gestion de la fusion (merge)

La gestion des conflits de modifications implique une configuration préalable, notamment celle d’un outil de gestion de fusion. Pour cela il faudra executer les commandes:
git config --global merge.tool vimdiff
git config --global merge.conflictstyle diff3
git config --global mergetool.prompt false
Ceci configure l’utilisation de l’outil en ligne de commande vimdiff pour la fusion du contenu des fichiers. Il existe plusieurs outils de gestion de fusion utilisables avec Git, dont certains avec interface graphique tel que kdiff3. Pour l’utiliser, il suffit de remplacer vimdiff par kdiff3 dans la commande de configuration. Il est utile de rappeler que cette configuration peut être affinée localement pour chaque projet en utilisant –local à la place de –global. Il est également utile de savoir qu’on peut consulter à tout moment les paramètres configurés par:
git config --global -l

 3. Conflit simple à la modification d’un seul fichier

DEV1 modifie la quatrième ligne de hello.sh (en italien), de façon qu’elle comporte 2 points d’exclamation à la fin au lieu d’un seul. DEV2 modifie la même ligne dans le même fichier mais en effaçant tout sauf le mot Ciao auquel il ajoute 4 points d’exclamation. DEV1 puis DEV2 executent les commandes:
git commit -am "Modification du message italien"
git push
La dernière commande de DEV2 échoue évidemment. Il execute alors:
git pull
Sans le paramètre –no-edit cette fois. Un message en réponse à cette commande indique qu’il y a un conflit de modification qu’il convient de résoudre. Pour le résoudre DEV2 execute:
git mergetool
Cette commande ouvre l’outil de merge configuré (vimdiff dans notre cas): Tuto Git - MergeQuatre versions du fichier hello.sh sont ouvertes dans quatre quadrants. En réalité il s’agit de 3 + 1 versions, la dernière étant le fichier résultat à obtenir et non pas une version réellement actuelle. C’est pour cela que ce procédé est dit Three-Way merging. Dans le volet d’en haut, les trois versions existantes. De gauche à droite (remarquer le nom du fichier indiquée dans la barre d’en bas): la version LOCALe (modification de DEV2), la version de BASE (version avant les modifications) et enfin la version REMOTE (dernière version sur le serveur, modification de DEV1). Dans le volet d’en bas le fichier cible, fusionné mais avec des marques (tags) pour indiquer les différentes modifications en conflit à arbitrer. Il s’agit d’un point de départ créée automatiquement par Git, à modifier impérativement pour nettoyer les tags rajoutés. Pour obtenir le résultat souhaité dans le fichier fusionné (cadrant d’en bas), on peut récupérer l’un des trois contenus, modifier le contenu manuellement ou les deux. On suppose ici qu’on voudrait obtenir le contenu suivant de la ligne modifiée et qui ne correspond à aucune des versions existantes:
Ciao tutti !!!!
Le plus proche de ce contenu est celui de la version locale, donc on va récupérer la version locale, la modifier et l’enregistrer. En premier on positionne le curseur dans la zone taggée en conflit. Cette zone commence par la ligne “<<<<<<< HEAD“. Pour ceux qui ne sont pas habitué à l’éditeur VI (ou VIM):  Pour naviguer entre les cadrants: commande Control-w, c’est à dire touche controle du clavier + w en même temps. Pour exécuter une commande: touche : du clavier, le curseur se positionne alors dans la dernière ligne du cadrant actif, on saisi alors la commande puis la touche entrée du clavier. Ensuite, on execute la commande de récupération du contenu du fichier local. on tape la touche : (lancer une commande dans vi) et ensuite dans la barre d’en bas on saisi:
diffget LOCAL
Tuto Git - MergeAprès la validation de cette commande (touche Entrée), le contenu change et les tags du conflit disparaissent. On modifie la ligne pour obtenir le résultat souhaité (Ciao tutti !!!!) puis on enregistre et on quitte. Pour enregistrer [:w], pour quitter [:qa]. On peut également utiliser les deux commandes en même temps [:wqa]. Enfin il convient, bien entendu, de valider et envoyer les modifications.
git commit -am "Modification arbitrée du message italien"
git push
De son côté, DEV1 peut alors récupérer le résultat en lançant la commande git pull.

4. Conflits multiples sur plusieurs fichiers

En suivant le même mode opératoire pour chacun des conflits, on les résout un à un et on enregistre et quitte. Tant qu’il reste un fichier encore en conflit dans la liste, git relance l’outil de gestion de fusion sur le fichier suivant qu’il convient de résoudre de la même manière. Dans un prochain article on traitera un exemple concret de ce cas de figure.]]>