Archives de catégorie : Tuto Git

Tuto Git – Suivi de l’évolution de fichiers et projets

Objectif: Suivre de manière efficace l’évolution des fichiers d’un projet logiciel contrôlé par Git. Utiliser les tags git pour marquer les versions de cette évolution.
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 les manipulations de l’article qui traite des fusions exécutées.

1. Visualiser les traces de l’évolution d’un fichier

On considère la situation atteinte à la fin du précédent article de la serie « Tuto Git ». DEV1 (cd /pcdev1) souhaite visualiser l’avolution du fichier README. Il exécute:

git log README

Le résultat obtenu est le suivant, marqué en couleur jaune l’indication de la fusion effectuée:

Tuto GitTrace de l’évolution du fichier README

Cette visualisation peut être améliorée en utilisant le paramètre graph:

git log --graph README

Le résultat obtenu est le suivant, marqué en couleur jaune l’indication de la fusion effectuée. Remarquer l’indication du conflit par la segmentation du « parcours » du fichier dans le temps:

Tuto GitTrace de l’évolution du fichier README avec représentation graphique

2. Créer un tag pour un projet

A tout moment au cours de l’évolution du projet on peut poser un tag sur l’ensemble du dépôt de fichiers source. Ceci permet de revenir ultérieurement vers cette image du projet. Dans la pratique un tag est posé à chaque fois que le projet atteint un certain niveau de maturité, notamment à l’occasion de la diffusion d’une version.

DEV2 (cd /pcdev2) ajoute d’abord la ligne suivante à la fin du fichier README:

Evolution de la version 1.0

Ensuite il pose un tag pour marquer la version 1.0

git tag -a v1.0 -m "Version 1.0"
git commit -am "Evolution vers une version stable"
git push
git tag

Remarquer la réponse à la dernière commande qui permet d’afficher la liste des tags disponibles.
DEV1 (cd /pcdev1) récupère cette évolution et regarde s’il y a des tags:

git pull
git tag

Curieusement aucun tag n’apparaît. L’explication à ceci est que le tag posé par DEV2 est resté local au dépôt de DEV2, un push simple ne permet pas d’envoyer les tags sur le serveur.

Pour remedier à cela DEV2 (cd /pcdev2), exécute de son côté:

git push --tags

Maintenant DEV1 récupèrera le tag posé après un git pull.

3. Revenir à une version (tag) précédente du projet

Après avoir récupéré les dernières modifications avec le tag, DEV2 exécute, pour récupérer la version 1.0:

git checkout v1.0
cat README

La commande checkout permet ivc de se positionner sur un tag existant.

Encore une fois curieusement, le contenu de README affiché avec la commande cat ne montre pas la dernière mise à jour (ajout de la ligne « Evolution de la version 1.0 »). Ce « mystère » peut être illucidé grâce à la commande:

git log --decorate README

La réponse à cette commande est:

Tuto GitOn est bien positionné sur le tag v1.0 (premier commit dans la liste) mais ce commit n’est pas le dernier en date. La cause est que le tag a été posé avant le dernier commit (paragraphe 2). Le tag est créée est positionné sur le dernier commit existant au moment de la création. Pour s’assurer de cette explication, DEV2 exécute successivement les commandes:

git checkout master
git log --decorate --graph README

La commande git checkout master permet de revenir à tout moment au dernier commit en date. La réponse à ces commandes est:

Tuto GitLa commande cat README permet de s’assurer également que le contenu de ce fichier est bien celui de la dernière mise à jour.

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.

Tuto Git – Modifications simultanées de fichiers sans conflit

Objectif: Ce 3eme article dans la série « Tuto Git » a pour objectif de montrer une séquence de travail simultané sur les fichiers du même projet par deux développeurs différents. Il traite les cas de modifications sans conflit.

Pré-requis: Les deux articles précédents sur l’installation et l’utilisation de Git sont lus et les manipulations exécutées.

1. Modification de fichiers différents:

Bien entendu ce cas de figure ne génère jamais de conflit. La modification inclu l’ajout et la suppression de fichiers. On part de la situation de l’article précédent.

DEV1 modifie le fichier hello.sh en ajoutant des lignes:

echo "Hello world !" >> hello.sh
echo "Hola todo el mundo !" >> hello.sh
echo "Ciao mondo !" >> hello.sh

Ensuite il crée un nouveau fichier hello.txt avec l’éditeur vi:

vi hello.txt

Ajouter les lignes puis enregistrer:

Ce projet permet d'afficher bonjour dans les langues suivantes:
Français
Anglais
Espagnole
Italien

Il valide ensuite ses modifcations et les envoi sur le serveur Git:

git add hello.txt
git commit -am "Ajout de 3 langues"
git push

Le paramètre -am de la commande git commit permet d’indexer en une seule fois les modifications en ajoutant le commentaire.

DEV2 de son côté, supprime le fichier hello.doc, pour cela il execute:

git rm hello.doc
git commit -am "Suppression de hello.doc"
git push

La dernière commande (envoi vers le serveur) échoue, le message de retour est claire: la copie locale n’est pas synchronisée avec le serveur. Il faudra executer:

git pull --no-edit

Les modifications de DEV1 sont alors récupérées.

git push

Cette fois l’envoi réussit.

A ce niveau DEV1 ne pourra plus rien envoyer (push) avant de synchroniser sa copie de travail (pull). En tentant de le faire il obtiendra le même message d’erreur. Il a toujours le fichier hello.doc en local:

ls -l
git pull --no-edit
ls -l

Après la synchronisation (pull), le fichier hello.doc disparaît.

2. Modifications simultanées d’un même fichier:

Dans la situation actuelle DEV1 et DEV2 ont des copies locales identiques et synchronisées avec le serveur. DEV1 modifie le fichier hello.sh en modifiant uniquement la première ligne (ancien contenu: « Boujour tout le monde ! ») qui devient: « Boujour monde ! »

git commit -am "Modification message Français"
git push

En même temps DEV2 modifie le même fichier hello.sh en modifiant la troisième ligne (ancien contenu:« Hola todo el mundo ! ») qui devient: « Hola mundo ! »

git commit -am "Modification message Espagnol"
git push

La commande d’envoi au serveur push échoue car la copie locale n’est plus synchronisée.

git pull --no-edit
cat hello.sh

Les deux modifications sont fusionnées car il n’y a pas de conflit entre les deux.

git push

Permet alors d’envoyer la modification vers le serveur. DEV1 devra exécuter la commande git pull pour récupérer la dernière version fusionnée.