CSC 4102 – Introduction au génie logiciel pour applications orientées objet

Portail informatique

Séance 1 — TP : Introduction à GitLab et à la gestion de versions avec Git

  • créer par copie (fork) puis configurer le projet GitLabEns du binôme-projet pour le module,
  • configurer son compte (machines TSP et machine personnelle) pour accéder à la forge logicielle GitLabEns avec sa paire de clefs (privée, publique) SSH,
  • être capable d'effectuer les manipulations de base sur le dépôt Git du projet GitLabEns.

GitLab Community Edition, GitLab dans la suite, est un logiciel libre proposant une « forge logicielle », c'est-à-dire une plateforme de gestion collaborative de développement de logiciels. L'objectif d'une telle plateforme est de rassembler des développeurs en communautés autour de projets logiciels. Télécom SudParis met à disposition un service GitLab pour l'enseignement ; nous l'appelons GitLabEns.

La plate-forme GitLabEns installée à TSP est réservée à l'utilisation pédagogique dans le cadre des enseignements, sur instruction expresse des enseignants. Merci de ne l'utiliser que dans ce cadre, et de ne pas y créer de projets personnels, associatifs ou autres. D'autres forges sont disponibles en Intranet ou sur Internet en cas de besoin de travail collaboratif avec Git. Veuillez par ailleurs noter que nous demandons la suppression de tous les projets CSC4102 pendant l'été, c'est-à-dire avant le début d'une nouvelle année universitaire. Donc, ne comptez pas sur la persistance de vos projets GitLabEns.

Une partie des manipulations proposées dans les étapes qui suivent sont librement inspirées du livre en ligne « Pro Git ».

Création et configuration du projet GitLabEns

  • créer un projet par binôme-projet, c'est-à-dire un membre du binôme-projet crée le projet et y ajoute ensuite le second membre,
  • rendre accessible votre projet à vos encadrants et au coordinateur du module CSC4102,
  • transmettre par courriel les informations du projet à votre responsable de groupe et au coordinateur du module.

Les premières étapes du TP reposent sur l'utilisation de GitLabEns via son interface Web, dans un navigateur. Par la suite, vous travaillez avec les outils ou commandes Git sur la machine locale.

si vous n'arrivez pas à vous connecter à la plateforme, voici le message de la DISI pour l'accès extérieur à la forge logicielle :
« Nous avons ouvert la plateforme GitLabEns depuis l’extérieur du campus a un nombre limité de Fournisseurs d'Accès Internet (FAI), principalement Orange, SFR, Bouygues, Free, mais il est possible que nous n'ayons pas énuméré toutes les adresses sources dont ils disposent. Si vous avez un refus d'accès, merci de retourner à la DISI via le helpdesk l’adresse Internet (adresse IP) de votre point d’accès (box, mobile, lieu d’hébergement...), adresse disponible depuis votre terminal en allant sur le site https://ip.lafibre.info/, afin que la DISI adapte les filtres IP d’accès à GitLabEns. Retournez l'information (adresse IPv4) obtenue sur cette page en envoyant un courriel : "Subject: contrôle d'acces IP à gitlab CSC4102, To: helpdesk@imtbs-tsp.eu, Body: contenu de https://ip.lafibre.info/" »

Connexion à un compte GitLabEns


les deux membres du binôme réalisent cette étape de première connexion à GitLabEns.

Vous vous connectez à la plateforme GitLabEns de TSP (https://gitlabens.imtbs-tsp.eu) en utilisant l'authentification Shibboleth repérée par le bouton suivant :

La première page sur laquelle vous arrivez est votre page d'accueil et ressemble à l'image suivante.

Création du projet GitLabEns


cette étape de création du projet est réalisée avec le compte d'un des membres du binôme-projet, l'autre membre étant ajouté une fois le projet créé.

Plutôt que de créer un projet en partant de zéro, vous partez d'un modèle de projet préparé pour le module. Ci-après, vous recopiez ce projet GitLabEns (par l'opération fork). Ce modèle de projet contient notamment un dépôt Git déjà peuplé.

Parcourez la liste des projets (onglet Projects dans le haut de la page à côté de l'onglet Your work). En commençant à taper csc4102... dans le formulaire de recherche, vous devez voir le projet enseignants.csc4102/csc4102-projet.

il est interdit de renommer votre projet GitLabEns car nous utilisons le nom « csc4102-projet » dans les scripts pour le suivi entre les séances ainsi que pour l'évaluation à la fin du module.

Ouvrez la page du projet enseignants.csc4102/csc4102-projet. Au dessus du bouton Clone, vous devez voir le bouton Fork (ou « Fourcher ») de l'image qui suit. Cliquez sur le bouton Fork.

Sélectionnez votre compte utilisateur comme « namespace » de la copie du projet. Profitez-en pour demander que le projet à créer soit privé.

En haut de la page du nouveau projet, un bandeau de couleur bleue affiche le message « The project was successfully forked. » comme montré dans l'image qui suit. Notez aussi que la page du projet indique la mention « Forked from enseignants.csc4102 ».

Si ce n'est pas déjà fait, dans le menu du projet à gauche, suivez l'entrée « Settings > General », puis Expand à la section Permissions. Rendez votre projet « privé » : Project Visibility > Private, et à la fin de cette section, Save changes. Le non-respect de cette règle revient à vous exposer aux mesures du paragraphe « Fraude » du règlement de scolarité.

Ajout des membres à votre projet


Le second membre du binôme est à ajouter avec le rôle « Owner » afin que chaque membre du binôme ait le même rôle. Les personnes suivantes sont à ajouter à votre projet avec le rôle « Developer », voire « Maintainer » :

  • pour le groupe de TP 1 : Chantal Taconet (en tant que responsable du groupe de TP) et Denis Conan (en tant que coordinateur du module),
  • pour le groupe de TP 2 : Georgios Bouloukakis (en tant que responsable du groupe de TP) et Denis Conan (en tant que coordinateur du module),
  • pour le groupe de TP 3 : Denis Conan (en tant que responsable du groupe de TP et en tant que coordinateur du module),
  • pour le groupe de TP 4 : Élisabeth Brunet et Sophie Chabridon (en tant que responsables du groupe de TP) et Denis Conan (en tant que coordinateur du module),
  • pour le groupe de TP 5 : Paul Gibson (en tant que responsable du groupe de TP) et Denis Conan (en tant que coordinateur du module),
  • pour le groupe de TP 6 : Olivier Berger et Michel Simatic (en tant que responsable du groupe de TP), et Denis Conan (en tant que coordinateur du module).

Pour ce faire, retrouvez dans le menu du projet à gauche l'entrée « Manage » puis « Members ». Cette entrée de menu vous conduit à la page de gestion des membres du projet. Dans cette page listant les membres, sélectionner le lien « Invite members » pour rechercher les nouveaux membres parmi les utilisateurs connus par la plateforme. Ajoutez d'abord votre binôme comme indiqué dans l'image qui suit.

Pour trouver votre binôme dans la liste des inscrits à la plateforme, il faut qu'elle ou il se soit connecté au moins une fois via Shibboleth.

Enfin, ajoutez les membres de l'équipe enseignante cités ci-avant avec le rôle « Developer », voire « Maintainer ».

Configuration de la fonctionnalité Emails on push


Lorsque vous travaillez, vous n'êtes pas forcément avec votre binôme et avec vos encadrants. Aussi, GitLab propose une fonctionnalité qui consiste à envoyer un courriel d'annonce à tous les membres du projet lorsque des modifications sont poussées sur le dépôt Git de GitLabEns.

Dans le menu du projet à gauche, sélectionnez l'entrée « Settings > Integrations », puis la page Emails on push.

Comme présenté dans l'image qui suit, configurez le service pour le rendre « active » sur les événements « Push » et « Tag push » avec l'adresse de l'émetteur étant celui qui pousse (case « Send from committer » cochée), et ajoutez les adresses courriels de tous les membres du projet (les deux membres du binôme ainsi que les membres de l'équipe enseignante que vous avez ajoutés à votre projet) dans le formulaire « Recipients ». N'oubliez pas de valider la nouvelle configuration avant de quitter la page.

Félicitations ! Votre projet GitLabEns est prêt pour le démarrage.

Accès SSH au dépôt Git du projet GitLabEns

Afin de pouvoir travailler avec le dépôt Git du projet que vous venez de créer sur GitLabEns, les commandes comme git pull, git fetch, git push, doivent se connecter de façon sécurisée à GitLabEns. Pour ce faire, dans le module, nous utilisons Git via le protocole SSH. Pour éviter d'avoir à taper un mot de passe à chaque commande d'accès à GitLabEns, nous mettons en place un « chemin de confiance » entre le client SSH de votre machine de travail et le serveur SSH de GitLabEns.

Les manipulations effectuées dans cette étape sont sensibles. Si vous faites trop d'erreurs (dans la saisie d'un mot de passe, d'une passphrase, etc.), l'adresse IP de la machine que vous utilisez risque d'être automatiquement bloquée (mise dans une « black list ») par les systèmes de surveillance du réseau de Télécom SudParis. Si cela arrive, soit vous ouvrez un ticket pour la DISI en indiquant votre adresse IP à débloquer soit vous attendez 24h.

Accès SSH au dépôt Git du projet GitLabEns depuis les machines des salles de TP


Dans le menu GitLab de configuration de votre compte (non du projet) qui est accessible en haut à gauche à partir de l'image iconique de l'avatar de votre compte, sélectionnez l'entrée Profile. Puis, dans le menu à gauche de la page ouverte, suivez l'entrée « SSH Keys ». Vous arrivez sur une page contenant un formulaire pour enregistrer une clé publique : cf. l'image qui suit.

Sur la machine en salle TP, affichez dans la console votre clef publique par exemple avec la commande « cat ~/.ssh/id_rsa.pub ». Assurez-vous que le copier/coller contienne toute la clef : de la chaîne de caractères « ssh-rsa » à l'identifiant inclus. Remarquez lors du copier/coller dans l'interface Web de GitLab que l'identifiant devient ce que GitLab appelle le « titre » de la clef.

Lorsque vous ajoutez votre clé publique, GitLab vous envoie un courriel ayant pour sujet « SSH key was added to your account ».

Pour vérifier que votre clef est correctement installée, nous vous demandons d'exécuter une commande ssh dans un terminal. Lors de la première connexion SSH à la machine git@gitlabens.imtbs-tsp.eu, la commande ssh pose la question « Are you sure you want to continue connecting (yes/no)? » sur la vérification de la clef publique de la machine distante. Veuillez vérifier que l'empreinte (en anglais, fingerprint) est l'un des suivants (il existe plusieurs algorithmes de prise d'empreinte [fonctions de hachage] que votre client SSH peut utiliser) :

2048 SHA256:co9NyLXXRPBp8EvWQxZcFI8BfX3N3T41LCGnSJIWftE gitlabens.imtbs-tsp.eu (RSA) 256 SHA256:XJlCXEvrN/K4UvzHX0Spj0xYDX67z8C+2dpx1Gk4QEU gitlabens.imtbs-tsp.eu (ECDSA) 256 SHA256:qFWcwH+C9BE++ubYn4k9f619Fn4IENFnI9wNZxkLmsk gitlabens.imtbs-tsp.eu (ED25519) 2048 MD5:83:d1:2b:2e:74:c1:d0:9d:fe:48:0d:b0:47:cf:f5:52 gitlabens.imtbs-tsp.eu (RSA) 256 MD5:87:ea:2a:73:a0:98:a1:d6:1a:dc:c5:00:e0:b7:02:bf gitlabens.imtbs-tsp.eu (ECDSA) 256 MD5:35:6f:8b:c0:8f:96:5f:7d:eb:d1:99:1b:f7:54:53:32 gitlabens.imtbs-tsp.eu (ED25519) 2048 xepez-gokiz-selev-ropep-dutus-tyrav-hefyp-zulul-kevih-golez-lexex gitlabens.imtbs-tsp.eu (RSA) 256 xulip-tavem-rogoc-kagiv-cudah-mylyc-goral-zegys-tytim-zoted-ryxix gitlabens.imtbs-tsp.eu (ECDSA) 256 xuvan-zules-podof-vicub-hedor-varyf-vidyt-voron-dogis-kymik-mixox gitlabens.imtbs-tsp.eu (ED25519)

Pour information, la DISI publie (un sous-ensemble des) les informations ici.

Voici maintenant la commande ssh que vous exécutez pour vérifier la mise en place du chemin de confiance entre la machine qui exécute la commande ssh et la machine qui fournit le dépôt Git gitlabens.imtbs-tsp.eu.

$ ssh -T git@gitlabens.imtbs-tsp.eu The authenticity of host 'gitlabens.imtbs-tsp.eu (157.159.10.68)' can't be established. ECDSA key fingerprint is SHA256:XJlCXEvrN/K4UvzHX0Spj0xYDX67z8C+2dpx1Gk4QEU. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'gitlabens.imtbs-tsp.eu,157.159.10.68' (ECDSA) to the list of known hosts. Welcome to GitLab, @VOTRE.COMPTE!
l'URL de connexion via SSH au dépôt Git est de la forme « git@gitlabens.imtbs-tsp.eu:... ». Il mentionne que vous vous connectez au serveur gitlabens.imtbs-tsp.eu via un nom de compte SSH unique (ici, « git »), cela quelque soit l'utilisateur Gitlab qui se connecte. L'identification des utilisateurs est réalisée par l'examen de la clé publique SSH présentée : ce sera celle que vous avez associée à votre compte GitlabEns dans la manipulation ci-dessus, si tout va bien.

Cette étape (enregistrement de clé SSH) est à refaire pour toutes les machines que vous utiliserez dans le cadre de CSC4102. Donc, cette étape est à exécuter au minimum sur une machine avec votre compte DISI en salle TP et sur votre machine personnelle.

Courriel à l'équipe enseignante


Pour le suivi, l'équipe enseignante a accès à votre projet GitLabEns. L'équipe enseignante utilise des scripts pour faciliter le suivi. Ces scripts se basent sur les informations suivantes que vous envoyez par courriel à votre responsable de groupe ainsi qu'au coordinateur du module. L'URL de votre projet pour un accès SSH est présenté sur la page d'accueil de votre projet. Voici les indications pour le courriel à envoyer :

- destinataires : 
  - vous
  - votre binôme
  - les membres de l'équipe enseignante : cf. liste ci-avant pour votre groupe de TP
- sujet : CSC4102, groupe de TP X
- corps :
  - URL HTTPS de votre projet GitLabEns : à copier/coller à partir de la page d'accueil
    de votre projet avec le bouton "code" puis "clone via HTTPS"
    (cette URL est de la forme https://gitlabens.imtbs-tsp.eu/xxx.yyy/csc4102-projet
    avec « xxx.yyy » qui sont les nom et prénom du membre du binôme qui a créé le projet [par fork])
  - URL SSH de votre projet Git sur GitLabEns : à copier/coller à partir de la page d'accueil
    de votre projet avec le bouton "code" puis "clone via SSH"
    (cette URL, appelée "URL_SSH_VOTRE_PROJET_GIT" ci-après ;
    l'URL est de la forme : git@gitlabens.imtbs-tsp.eu:xxx.yyyy/csc4102-projet.git
    avec « xxx.yyy » qui sont les nom et prénom du membre du binôme qui a créé le projet [par fork])

Accès SSH au dépôt Git du projet GitLabEns depuis votre machine personnelle


Sur votre machine personnelle, re-parcourez l'étape 2.a.

Félicitations ! Vous pourrez dorénavant travailler sur le projet avec SSH et Git.

Premières manipulations du dépôt Git du projet GitLabEns

  • opérer quelques configurations supplémentaires de Git,
  • récupérer le dépôt (commande git clone),
  • manipuler les premières commandes Git : git status, git add, git commit, git mv, git rm, git log, git reset, et git checkout.
  • manipuler les outils git gui, et gitk ou tig,

Configuration de Git


Avant de commencer à utiliser les commandes Git, nous complétons l'installation Git.

Certaines commandes Git que nous étudions dans la suite du TP, par exemple git commit et git merge, demandent la saisie d'un message de log dans un éditeur de texte. Par défaut, Git utilise l'éditeur de texte configuré pour le shell. Le choix de l'éditeur de texte est contrôlé par les variables VISUAL et EDITOR. Vous avez deux possibilités : (1) fixer les variables VISUAL et EDITOR à la valeur « emacs » ou (2) demander à Git de ne pas utiliser l'éditeur par défaut mais emacs. Si votre éditeur de texte favori est emacs, nous vous conseillons de faire les deux manipulations qui suivent.

Configurer l'éditeur de texte du shell Configurer l'éditeur de texte utilisé par Git
$ echo "export VISUAL=emacs" >> ~/.bashrc $ echo "export EDITOR=emacs" >> ~/.bashrc $ source ~/.bashrc
git config --global core.editor emacs

Git demande que vous indiquiez vos nom et adresse courriel pour les ajouter comme méta-données aux opérations de validation des instantanés (git commit). Exécutez les commandes qui suivent :

$ git config --global user.name "Votre_prénom VOTRE_NOM" $ git config --global user.email "votre_adresse_courriel"

Lors de la récupération des contenus modifiés par les autres membres du projet, Git demande à utiliser une procédure de réconciliation automatique de l'historique de votre projet. Nous proposons d'utiliser la méthode dite de fusion (pour les connaisseurs, plutôt que le rebasage ou l'avance rapide) : en quelques mots, toujours pour les connaisseurs, on garde les instantanés sans les changer. Nous vous proposons donc d'exécuter la commande qui suit :

$ git config --global pull.rebase false

Enfin, pour résoudre les conflits lors des fusions (cf. ci-dessous), Git peut utiliser un outil graphique. Nous proposons d'utiliser l'outil meld. Exécutez la commande qui suit :

$ git config --global merge.tool meld

Récupération du dépôt par clonage Git


Cette première étape de clonage du dépôt Git doit être effectuée par les deux membres du binôme et les autres étapes par uniquement un seul membre du binôme.

Avec la commande git clone, récupérez dans votre espace de travail (à l'intérieur du répertoire ~/CSC4102) une copie du dépôt Git de votre projet. C'est dans cette copie conforme (un clone) que vous travaillez.

$ # commencez peut-être par « mkdir ~/CSC4102 » $ cd ~/CSC4102 $ git clone URL_SSH_VOTRE_PROJET_GIT Clonage dans 'csc4102-projet'... ... $ cd csc4102-projet

Comme indiqué par l'affichage du message de la commande git clone, le dépôt n'est pas vide, mais contient le contenu initial qui vous est proposé pour démarrer le projet (vérifiez avec la commande ls -R).

Nous vous proposons de démarrer tout de suite l'outil gitk afin de visualiser l'historique des modifications du dépôt depuis le début de sa création (avant le fork). Dans toute la suite du TP, nous utilisons cet outil pour suivre la création des instantanés. C'est pour cela que vous devez démarrer gitk en arrière plan (« & »). Ceux qui préfèrent l'affichage en console de l'arbre des instantanés utiliseront la commande git log --graph --oneline ou l'outil tig.

$ gitk --all& # option --all pour avoir toutes les branches

Première manipulation du contenu du dépôt, premières commandes Git


Ajoutez votre premier contenu avec par exemple un fichier classique listant les participants au projet.

$ echo "Un Tel et Une Telle..." > AUTHORS.txt

Le nouveau fichier n'est pas encore sous suivi de version. La commande git status nous le dit :

$ git status Sur la branche main Votre branche est à jour avec 'origin/main'. Fichiers non suivis: (utilisez "git add ..." pour inclure dans ce qui sera validé) AUTHORS.txt aucune modification ajoutée à la validation mais des fichiers non suivis sont présents (utilisez "git add" pour les suivre)

Comme montré dans l'image qui suit, l'outil git gui donne graphiquement les mêmes informations que la commande git status.

$ git gui

Ajoutez ce nouveau fichier dans la zone de transit :

$ git add AUTHORS.txt $ git status Sur la branche main Votre branche est à jour avec 'origin/main'. Modifications qui seront validées : (utilisez "git restore --staged <fichier>..." pour désindexer) nouveau fichier : AUTHORS.txt

À nouveau, l'outil git gui donne graphiquement les mêmes informations que la commande git status. Dans la suite de la présentation, par économie visuelle, nous préférons utiliser git status.

Et maintenant, validez ce premier ajout pour construire votre premier instantané du dépôt Git :

$ git commit -m "ajout d'un fichier avec les auteurs" [main 0fd48d7] ajout d'un fichier avec les auteurs 1 file changed, 1 insertion(+) create mode 100644 AUTHORS.txt $ git status Sur la branche main Votre branche est en avance sur 'origin/main' de 1 commit. (utilisez "git push" pour publier vos commits locaux) rien à valider, la copie de travail est propre

Nous pouvons aussi voir notre premier instantané avec « gitk --all » en demandant la mise à jour du graphe présenté : menu Fichier > Mise à jour ou touche F5.

Prenez l'habitude de mettre un message significatif pour chacune de vos validations (commit).

Pour la suite des étapes, nous vous laissons vérifier l'effet de vos manipulations en utilisant à votre guise les commandes git status et gitk --all, voire git gui.

Gestion de la zone de transit


Dans cette étape, nous explorons l'ensemble des états possibles des entrées (cf. section 2.3 des diapositives du cours). Pour ce faire, nous commençons par ajouter un nouveau fichier (état « non suivi » [untracked]). Puis, nous ajoutons la nouvelle entrée à la zone de transit (staging area). L'entrée est alors dite indexée (cached ou staged). Enfin, nous modifions à nouveau le fichier qui est dans la zone de transit ; cela a pour effet d'avoir « trois versions » du même fichier : la « version » correspondant à l'instantané (snapshot) courant du répertoire de travail, la « version » correspondant à la zone de transit (c'est-à-dire celle qui sera dans la prochaine validation [commit]), et la « version » en cours de modification et dont les modifications ne font pas partie de la prochaine validation.

Nous utilisons la commande git status après chaque commande pour suivre ce qui se passe.

$ echo "Tache, contenu, date limite" > TODO $ git status ... $ git add TODO $ git status ... $ echo "Autre nouvelle information" >> TODO $ git status # les trois versions, dont deux différentes montrées par git status ... $ git add TODO $ git status ... $ git commit -m "ajout d'un fichier TODO"

Nous avons référencé la page de la documentation de référence dans la rubrique « Trucs & astuces » pour Git à la question « Des informations sur le cycle de vie des états des fichiers ».

À la fin de cette courte séquence, vous avez approximativement la visualisation suivante dans l'outil gitk.

Entrées ignorées et autres commandes de base


Vous avez du code écrit en JAVA dans votre dépôt : c'est l'ossature de départ de l'application contenue dans le répertoire src. Il est inutile dans ce cas d'encombrer le dépôt avec les fichiers résultant de la compilation, c'est-à-dire les fichiers *.class. En outre, si vous utilisez Eclipse, vous pouvez voir apparaître des répertoires spécifiques à Eclipse, par exemple un répertoire bin. Nous ne mettons pas non plus le workspace Eclipse dans le dépôt : pas de répertoires workspace ou .metadata. Par ailleurs, nous souhaitons ignorer les répertoires doc créés lors de la génération de la documentation Javadoc par Eclipse.

Toutes ces informations sont mises dans un fichier .gitignore, qui est ajouté à la racine de l'arborescence de votre dépôt. Par simplicité, nous avons choisi d'ajouter ce fichier dans le répertoire à la racine de l'arborescence du dépôt ; un autre choix serait de mettre plusieurs fichiers .gitignore pour les différentes sous-arborescences du dépôt.

Pour vérifier le fonctionnement de la configuration du fichier .gitignore, créez de manière artificielle (c'est-à-dire sans compilation) un fichier A.class.

$ touch A.class $ ls A.class $ git status Sur la branche main rien à valider, la copie de travail est propre

Il est bien sûr possible de forcer l'ajout d'un fichier qui est par défaut ignoré : par exemple, avec git add -f A.class. Nous pouvons ensuite en profiter pour utiliser la commande git mv pour déplacer ou renommer le fichier et la commande git rm pour supprimer cette entrée. Dans notre scénario, comme le fichier à supprimer est déjà dans la zone de transit, nous devons ajouter l'option -f pour forcer la suppression. Nous terminons la séquence avec la commande git log qui fournit un historique des modifications.

$ git add A.class Les chemins suivants sont ignorés par un de vos fichiers .gitignore : A.class Utilisez -f si vous voulez réellement les ajouter. $ git add -f A.class $ git mv A.class B.class $ git rm B.class error: le fichier suivant a des changements indexés : B.class (utilisez --cached pour garder le fichier, ou -f pour forcer la suppression) $ git rm -f B.class $ git log ...

Désindexation d'entrées et annulation de modifications


Il arrive que l'on souhaite retirer des modifications effectuées par erreur alors qu'elles sont déjà indexées, c'est-à-dire alors que les fichiers correspondants ont été ajoutés à la zone de transit. Lorsque nous souhaitons que les modifications ne fassent plus partie de la prochaine validation, tout en n'annulant pas les modifications en elles-mêmes, nous utilisons la commande git restore --staged. Une fois le fichier sorti de la zone de transit, si nous souhaitons en plus que les modifications soient annulées, c'est-à-dire que nous souhaitons revenir à la « version » du dépôt dans le dernier instantané, alors nous utilisons la commande git restore. De manière assez simple, la commande git status, dans sa version par défaut verbeuse, nous indique les commandes à utiliser.

$ echo "contenu non voulu" >> readme.md $ git add readme.md # dans ce qui suit, # lisez l'affichage résultant de l'exécution de la commande git status # comprenez les instructions proposées # et ne cherchez pas à retenir une commande comme la suivante # mais retenez que la commande git status la propose $ git status Sur la branche main Modifications qui seront validées : (utilisez "git restore --staged <fichier>..." pour désindexer) modifié : readme.md $ git restore --staged readme.md $ git status Sur la branche main Modifications qui ne seront pas validées : (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé) (utilisez "git restore <fichier>..." pour annuler les modifications dans la copie de travail) modifié : readme.md aucune modification n'a été ajoutée à la validation (utilisez "git add" ou "git commit -a") $ git restore readme.md $ git status Sur la branche main rien à valider, la copie de travail est propre

Pour information, les fichiers avec l'extension .md sont des fichiers de texte incluant quelques caractères de mise en forme au format markdown pour GitLab. Les caractères de mise en forme sont automatiquement convertis en HTML lors de la visualisation dans l'interface Web de GitLabEns. Par ailleurs, le fichier readme.md est utilisé comme page d'accueil de votre projet (ou d'un répertoire de votre projet).

Git, les branches, les fusions de branches et la gestion des conflits

  • gérer les branches (commandes git branch, git checkout),
  • gérer les fusions de branches, avec ou sans conflit (commandes git merge, git mergetool).

Fusion de branches sans conflit


Depuis le début des manipulations du dépôt Git, nous ne l'avons pas dit, mais vous êtes dans la branche main, qui est la branche créée au démarrage du dépôt. Dans le scénario virtuel qui suit, vous créez une première branche de travail (sprint0). Ensuite, vous indiquez dans un fichier la liste des tâches du Sprint 0. Enfin, vous simulez les opérations de la tâche 1 :

  1. création d'une branche tache1 (pour être « tranquille »),
  2. déplacement dans la branche tache1,
  3. travail sur la tâche,
  4. validation de ce travail,
  5. retour dans la branche du sprint (sprint0), et
  6. fusion de la branche de la tâche (tache1).

Normalement, les messages en sortie fournis par les commandes sont assez explicites. Notez que nous utilisons l'option --no-ff (no fast-forward) de la commande git merge afin de matérialiser la fusion dans un instantané dédié. Retenez aussi que vous pouvez observer le graphe des instantanés dans la console avec l'option --graph de la commande git log, l'option --oneline permettant de compacter l'affichage. Bien sûr, continuez aussi à utiliser « gitk --all » pour visualiser le graphe.

$ git branch sprint0 $ git checkout sprint0 Basculement sur la branche 'sprint0' $ echo F1 >> tachesPourSprint0.txt $ echo F2 >> tachesPourSprint0.txt $ echo F3 >> tachesPourSprint0.txt $ echo F4 >> tachesPourSprint0.txt $ git add tachesPourSprint0.txt $ git commit -m "Preparation du sprint0 avec la liste des taches" [sprint0 799388d] Preparation du sprint0 avec la liste des taches 1 file changed, 4 insertions(+) create mode 100644 tachesPourSprint0.txt $ git branch tache1 $ # travail sur la tache 1 $ git checkout tache1 Basculement sur la branche 'tache1' $ echo "contenu pour F1" > F1.txt $ git add F1.txt $ sed 's/F1/F1 -- terminé/' tachesPourSprint0.txt > tachesPourSprint0.txt.updated # les curieux exécuteront « man sed » $ mv tachesPourSprint0.txt.updated tachesPourSprint0.txt $ git add tachesPourSprint0.txt $ git commit -m "Debut et fin de la nouvelle tache F1" [tache1 5834a13] Debut et fin de la nouvelle tache F1 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 F1.txt $ git checkout sprint0 Basculement sur la branche 'sprint0' $ git merge --no-ff tache1 -m "fusion branche tache1 dans sprint0" Merge made by the 'recursive' strategy. F1.txt | 1 + tachesPourSprint0.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 F1.txt $ git log --graph --oneline * 32991eb fusion branche tache1 dans sprint0 |\ | * 5834a13 Debut et fin de la nouvelle tache F1 |/ * 799388d Preparation du sprint0 avec la liste des taches * 5483c23 ajout de .gitignore pour les entrees a ignorer * 62895bc notre second commit * 96f8213 premiers elements du projet

Fusion de branches avec conflit


Imaginons que vous continuiez votre travail dans le Sprint 0 en passant de tâches en tâches, et que vous créiez un scénario menant à un conflit inévitable :

  1. travail sur la tâche 2 dans une branche dédiée tache2 créée à partir de la branche sprint0 ;
  2. travail sur la tâche 3 dans une branche dédiée tache3 créée elle-aussi à partir du même instantané de la branche sprint0. Cette fois-ci, le travail sur la tâche 3 impacte le travail sur la tâche 2. En d'autres termes, certains fichiers sont modifiés concurremment dans les deux tâches/branches.
Voici le scénario :
$ git branch tache2 $ git branch tache3 $ # travail sur la tache 2 $ git checkout tache2 Basculement sur la branche 'tache2' $ echo "contenu pour F2" > F2.txt $ sed 's/F2/F2 -- juste commencé/' tachesPourSprint0.txt > tachesPourSprint0.txt.updated $ mv tachesPourSprint0.txt.updated tachesPourSprint0.txt $ git add F2.txt tachesPourSprint0.txt $ git commit -m "Debut de la tache F2" [tache2 5cf9e8e] Debut de la tache F2 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 F2.txt $ # travail sur la tâche 3 $ git checkout tache3 Basculement sur la branche 'tache3' $ echo "contenu pour F3" > F3.txt $ sed 's/F3/F3 -- terminé/' tachesPourSprint0.txt > tachesPourSprint0.txt.updated $ mv tachesPourSprint0.txt.updated tachesPourSprint0.txt $ echo "autre début de contenu pour F2" > F2.txt $ sed 's/F2/F2 -- commencé/' tachesPourSprint0.txt > tachesPourSprint0.txt.updated $ mv tachesPourSprint0.txt.updated tachesPourSprint0.txt $ git add F2.txt F3.txt tachesPourSprint0.txt $ git commit -m "Nouvelle tache F3 avec début tache F3" [tache3 f7a3389] Nouvelle tache F3 avec début tache F3 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 F2.txt create mode 100644 F3.txt $ # fusion à proprement parler $ git checkout sprint0 Basculement sur la branche 'sprint0' $ git merge --no-ff tache2 -m "fusion branche tache2 dans sprint0" Merge made by the 'recursive' strategy. F2.txt | 1 + tachesPourSprint0.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 F2.txt $ git merge --no-ff tache3 -m "fusion branche tache3 dans sprint0" Fusion automatique de tachesPourSprint0.txt CONFLIT (contenu) : Conflit de fusion dans tachesPourSprint0.txt Fusion automatique de F2.txt CONFLIT (ajout/ajout) : Conflit de fusion dans F2.txt La fusion automatique a échoué ; réglez les conflits et validez le résultat. $ git status Sur la branche sprint0 Vous avez des chemins non fusionnés. (réglez les conflits puis lancez "git commit") (use "git merge --abort" to abort the merge) Modifications qui seront validées : nouveau fichier : F3.txt Chemins non fusionnés : (utilisez "git add ..." pour marquer comme résolu) ajouté de deux côtés : F2.txt modifié des deux côtés : tachesPourSprint0.txt $ cat F2.txt >>>>>> tache3 $ cat tachesPourSprint0.txt F1 -- terminé >>>>>> tache3 F4

Nous sommes maintenant dans une situation de conflit. Nous devons construire une version des deux fichiers en résolvant les conflits, c'est-à-dire sans les balises « <<<<<<< », « ======= » et « >>>>>>>> ». Nous pourrions faire cela en ouvrant un éditeur de texte. Nous choisissons de nous aider de l'outil de fusion meld. Voici la commande :

$ git mergetool --tool=meld Merging: F2.txt tachesPourSprint0.txt Normal merge conflict for 'F2.txt': {local}: created file {remote}: created file

Dans l'image ci-après, le fichier en cours de traitement est F2. L'objectif de la résolution du conflit est d'aligner les trois versions en utilisant les flèches.

Choisissons par exemple la version du fichier de la branche de la tâche 3 (fichier F2_REMOTE_4365.txt). Nous obtenons l'image suivante.

Nous terminons l'étude du fichier F2 en enregistrant les modifications : bouton Enregistrer et menu Fichier, puis Save All. Ensuite, nous fermons la fenêtre et une autre fenêtre s'ouvre pour la seconde résolution de conflit : fichier tachesPourSprint0.txt. Nous opérons similairement en choisissant la version de la branche de la tâche 3.

Nous terminons notre scénario comme suit :

$ git status Sur la branche sprint0 Tous les conflits sont réglés mais la fusion n'est pas terminée. (utilisez "git commit" pour terminer la fusion) Modifications qui seront validées : modifié : F2.txt nouveau fichier : F3.txt modifié : tachesPourSprint0.txt Fichiers non suivis: (utilisez "git add ..." pour inclure dans ce qui sera validé) F2.txt.orig tachesPourSprint0.txt.orig $ git commit -m "fusion branche tâche3 dans sprint0" [sprint0 9d36236] fusion branche tâche3 dans sprint0 $ git log --graph --oneline * 9d36236 fusion branche tâche3 dans sprint0 |\ | * f7a3389 Nouvelle tâche F3 avec début tâche F3 * | 7f229a3 fusion branche tâche2 dans sprint0 |\ \ | |/ |/| | * 5cf9e8e Début du nouvelle tâche F2 |/ * fd016ef fusion branche tâche1 dans sprint0 |\ | * af0a361 Début et fin de la nouvelle tâche F1 |/ * 1aeb5ad Préparation du sprint0 avec la liste des tâches * 6734822 ajout de .gitignore pour les entrees a ignorer * daa964c notre second commit * a9a37de premiers elements du projet

Fin de l'exercice sur la gestion des branches


Pour terminer proprement l'exercice, revenez sur la branche main et fusionnez-la avec la branche sprint0.

$ git checkout main $ git merge --no-ff sprint0

Processus de travail proposé pour l'utilisation de Git dans le module CSC4102

Git propose beaucoup de commandes, mais pas de méthodologie pour organiser le travail en équipe via la forge logicielle. Par analogie, UML propose des notations, mais pas de processus de développement. Par expérience, l'équipe enseignante vous propose le processus de travail (en anglais, workflow) suivant : A successful Git branching model, de Vincent Driessen.

  • pousser les modifications sur le dépôt Git de GitLabEns (commande git push),
  • mettre à jour le dépôt local (commandes git fetch et git pull),
  • mettre en place la branche develop pour le développement.

Le processus proposé dans le module CSC4102 est visualisé dans la figure qui suit, avec le chemin de confiance construit avec SSH, et les échanges impliqués par les commandes Git.

Situation de fin d'une séquence de travail


Les modifications de l'étape précédente n'existent que dans le dépôt Git sur la machine ou sur le compte d'un membre du binôme. Poussez vos modifications, c'est-à-dire vos instantanés, sur le dépôt Git de la forge logicielle GitLabEns afin que par la suite les autres membres du projet (l'autre membre du binôme ainsi que les encadrants) en prennent connaissance et les récupèrent dans leur dépôt local.

$ git push origin main Décompte des objets: 28, fait. Compression des objets: 100% (18/18), fait. Écriture des objets: 100% (28/28), 2.54 KiB | 865.00 KiB/s, fait. Total 28 (delta 10), reused 0 (delta 0) To gitlabens.imtbs-tsp.eu:.../csc4102-projet.git 86a5c4e..bc9308b main -> main

Situation de reprise du travail


Dans cette étape, utilisez le compte du second membre du binôme-projet, c'est-à-dire autre que celui utilisé à l'exercice précédent. Cela permet de présenter les commandes git fetch et git pull.

Comme demandé au début de l'étape précédente, le second membre du binôme-projet possède déjà une « copie » du dépôt. Le dépôt a évolué depuis le clonage. Le processus classique de reprise est le suivant :

  • récupération des mises à jour,
  • (au besoin) déplacement sur la branche sur laquelle on souhaite travailler,
  • repositionnement sur le dernier instantané d'une branche.
$ git fetch remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0) Dépaquetage des objets: 100% (3/3), fait. Depuis gitlabens.imtbs-tsp.eu:.../csc4102-projet * [nouvelle branche] main -> origin/main $ git pull origin main Depuis gitlabens.imtbs-tsp.eu:.../csc4102-projet * branch main -> FETCH_HEAD

Mise en place du dépôt pour le démarrage du développement : branche develop


Nous terminons donc la séance par la mise en place de l'arborescence de votre projet GitLab pour les séances à venir.

Créez la branche develop en utilisant la commande git checkout avec l'option -b pour créer la branche et vous déplacer dedans (c'est un raccourci des deux commandes git branch pour créer la branche puis git checkout pour se positionner dans la branche créée).

$ git checkout -b develop Basculement sur la nouvelle branche 'develop' $ # on pousse tout de suite la création de la nouvelle branche $ git push origin develop Total 0 (delta 0), réutilisés 0 (delta 0), réutilisés du pack 0 remote: remote: To create a merge request for develop, visit: remote: https://gitlabens.imtbs-tsp.eu/denis.conan/csc4102-projet/-/merge_requests/new?merge_request%5Bsource_branch%5D=develop remote: To gitlabens.imtbs-tsp.eu:denis.conan/csc4102-projet.git [new branch] develop -> develop

À la fin du TP, l'outil gitk donne une image comme la suivante. Observez :

  • les branches, dont certaines sont locales (celles du travail sur les tâches de notre petit scénario ne sont pas dans le dépôt Git de GitLabEns car vous ne les avez pas poussées avec git push ; vous pourriez les supprimer avec la commande git branch -d tache1, etc.) ;
  • la branche main du dépôt Git de GitLabEns (repérée dans gitk par le nom remotes/origin/main) est alignée avec (à jour de) vos modifications ;
  • la branche develop du dépôt Git de GitLabEns (repérée dans gitk par le nom remotes/origin/main) est alignée avec (à jour de) vos modifications ; et
  • que, de manière plus subtile dans l'affichage, on voit que vous êtes sur la branche develop car le texte de la boîte verte « develop » est en graisse forte (les autres non).

Dans l'interface Web de GitLabEns, vous pouvez voir la séquence de commits : dans la page d'accueil du projet, suivez l'entrée « Repository » puis Commits pour obtenir une page comme l'image suivante.

Félicitations ! Vous êtes prêts pour démarrer le projet.

Clonage du projet GitLabEns contenant les exemples du module

Le projet csc4102-exemples contient tous les exemples de modélisation et de code source utilisés dans les cours du module. Clonez-le et prenez connaissance du fichier readme.md.

$ cd ~/CSC4102 $ git clone git@gitlabens.imtbs-tsp.eu:enseignants.csc4102/csc4102-exemples.git Clonage dans 'csc4102-exemples'... remote: Enumerating objects: 623, done. remote: Counting objects: 100% (623/623), done. remote: Compressing objects: 100% (376/376), done. remote: Total 623 (delta 212), reused 623 (delta 212) Réception d'objets: 100% (623/623), 2.20 Mio | 44.21 Mio/s, fait. Résolution des deltas: 100% (212/212), fait. $ cd csc4102-exemples $ cat readme.md ...

À LA FIN DU TP DE LA SÉANCE

Avant de quitter le TP, veuillez s'il vous plaît remplir dans la page Partage de votre groupe le tableau d'avancement de votre binôme-projet :

C'est aussi le moment de parcourir la grille d'auto-évaluation de la séance.

Félicitations ! Vous avez terminé la séance 1 et êtes prêts pour préparer la séance 2 (avec la lecture du cahier des charges).