Tag Archives: Git merge

Tuto Git – Fusion de modifications de fichiers avec conflits multiples

Objectif: Comprendre la démarche pour effectuer une fusion (merge) de plusieurs fichiers avec des conflits de modification multiples. Pré-requis: Git est installé et confiiguré sur un système GNU/Linx (article 1 de la serie « Tuto Git ». Les commandes de base sont connues et un outil de fusion (mergetool) est configuré.

1. Ajouter un troisième développeur à la simulation

Exécuter dans l’ordre:
sudo mkdir /pcdev3
sudo chown login:login /pcdev3
cd /pcdev3
git clone /serveurgit/hello.git
cd hello
git config --local user.email "DEV3@server.com"
git config --local user.name "DEV3"

2. Ajouter un fichier qui va subir les conflits multiples de modification.

DEV3 crée un nouveau fichier README (avec l’éditeur vi par exemple) et l’ajoute au dépôt. Le contenu de ce fichier est:
Pour utiliser ce logiciel d'affichage de messages:
./hello.sh
La réponse sera:
Affichage
Bonjour tout le monde en 4 langues.
Ensuite, DEV3 exécute:
git add README
git commit -m "Création de README"
git push
Suite à cela DEV1 et DEV2 exécutent: git pull, chacun de son côté, pour récupérer le nouveau fichier.

3. Effectuer les modifications des fichiers pour se mettre en situation.

3.1. DEV3 (cd /pcdev3) modifie le fichier README pour que son contenu devienne:

Pour utiliser ce logiciel exécuter:
./hello.sh
La réponse est alors:
Affichage
"Hello world" d'abord, ensuite 3 autres langues.
Ensuite il exécute:
git commit -am "Modification de README"
git push

3.2. DEV2 (cd /pcdev2) modifie le fichier hello.txt pour que le contenu de la 1ere ligne devienne:

Affichage de "bonjour tout le monde" dans les langues suivantes:
Ensuite il exécute:
git commit -am "Modification de la 1ere ligne de hello.txt"
git push

3.3. DEV1 (cd /pcdev1) modifie le fichier README pour que son contenu devienne:

Utilisation:
./hello.sh
Réponse:
Affichage
"Bienvenue" en 4 langues.

3.4. DEV1 modifie le fichier hello.txt pour que le contenu de la 1ere ligne devienne:

"Bienvenue" en:

4. Fusion des deux fichiers en conflit.

Quand DEV1 tentera d’envoyer ses modifications sur le serveur, il y aura 4 conflits: 3 dans README et 1 dans hello.txt. DEV1 exécute donc:
git commit -am "Simplification de README et hello.txt"
git push
La deuxième commande échoue à cause du conflit, DEV1 doit alors effectuer une fusion (merge).
git pull
git mergetool
l’outil paramétré (ici vimdiff) est lancé et DEV1 peut arbitrer les conflits un à un:

tuto gitMerge du fichier hello.txt – affichage initial

tuto gitDéplacer le curseur dans la zone du conflit et lancer la commande: diffget LOCAL, pour récupérer la copie locale

tuto gitAprès la validation de la commande diffget le conflit est résolu et la modification doit être enregistrée (:wqa)

tuto gitAussitôt l’enregistrement effectué, l’outil passe au fichier suivant en confli: README

tuto gitAprès la résolution, de la même manière des trois zones de conflit dans ce fichier, l’enregistrement entraine la fin du traitement (:wqa)

Pour valider l’arbitrage effectué:
git commit -m "Fusion"
git push
Bien entendu, à ce stade seul DEV1 dispose en local de la version finale issur de la fusion. DEV2 et DEV3 doivent exécuter git pull pour synchroniser leurs copies locales respactives.]]>

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.]]>