Tutoriel Git

Prérequis

Pour comprendre ce TP, il est nécessaire comprendre :

Prenez le temps de les aborder en cliquant sur les liens si vous n'êtes pas à l'aise, sinon vous serez perdu.

Notions clefs

  1. Dépôt (repository)

Un ensemble de fichiers consituant le code source d'un programme que l'on désignera comme un projet est enregistré dans un répertoire. La figure ci-dessous illustre un répertoire avec un projet.

repository

Le répertoire caché .git est nommé le dépôt ("repository" en anglais). Ce répertoire contient l’historique des modifications du projet. Le dossier du projet ne contient qu'une version des fichiers du projet (la dernière version).

  1. Commit

L’historique d'un projet est une séquence de "photos" de l’état du projet à un moment donné. On appelle ces "photos" des commits.

Les commits possèdent
  • Une date

  • Un auteur

  • Une description textuelle

  • Un lien vers le(s) commit(s) précédent(s)

commit
  1. Copie de travail

On appelle "Copie de travail" les fichiers effectivement présents dans le répertoire géré par Git. Leur état peut être différent du dernier commit de l’historique.

  1. Index

L’index est un espace temporaire contenant modifications prêtes à être « commitées ». Ces modifications peuvent être :

  • Création de fichier

  • Modification de fichier

  • Suppression de fichier

On doit ajouter un fichier à l’index pour qu’il soit pris en considération.

Note

Que l'on apprécie ou pas, l'utilisation de mots francisés tels que "commiter" est la norme dans le monde du développement. Nous nous permettrons donc l'utilisation de tels anglicismes plutôt que d'utiliser des termes français correct qui ne sont en réalité pas d'usage chez les développeurs.

Installation de Git

Avertissement

Cette partie du TP est à faire individuellement, car tout le monde aura besoin de ces connaissances.

Si vous ne l'avez pas encore, vous devez installer Git. Voici un tutoriel pour vous y aider : https://wiki.student.info.ucl.ac.be/Logiciels/Git.

Avertissement

Utilisateurs Windows, attention !

Par défaut, Windows cache les extensions des fichiers. Cela veut dire que dans l'explorateur Windows, si vous créez un fichier appelé README.md, il s'appellera en fait README.md.txt.

Vous devez afficher les extensions sur Windows. En tant qu'informaticien·ne·s, c'est inévitable.

  1. Allez dans l'explorateur Windows

  2. Allez dans Option dans la barre du dessus. Cela peut être caché sous le symbole ...:

Menu options de l'explorateur windows
  1. Dans l'onglet affichage...

Liste des choix dans le panneau affichage
  1. Décochez Masquer les extensions des fichiers dont le type est connu.

  2. Cliquez sur Ok

Utilisation de Git localement

Création d'un dépôt Git

Créez d'abord un répertoire MyProject. Pour initialiser un dépôt Git local, naviguez jusqu'au répertoire que vous venez de créer et utilisez la commande git init . Cela crée un sous-répertoire caché appelé .git qui contient toutes les informations de suivi de version de votre projet.

Ajouter des fichiers au dépôt et commits

Créez un fichier nommé README.md dans le répertoire MyProject et ajoutez une phrase de votre choix.

Pour ajouter le fichier README.md à l'index, utilisez la commande git add suivie du nom du fichier, par exemple :

$ git add README.md

Pour enlever un fichier de l'index, utilisez la commande git rm suivie du nom du fichier, par exemple :

$ git rm README.md

Pour afficher le statut de l'index, utilisez la commande git status.

Enregistrer les modifications de l'index dans le dépôt

Pour enregistrer les modifications de l'index dans le dépôt, utilisez la commande git commit. Voici un exemple : git commit -m "Ajout du fichier README.md"

Commentaires sur les commits :
  • Il faut un message pour faire un commit sur git.

  • Le message de commit doit indiquer clairement les modifications apportées au contenu du dépôt.

Ajoutez un second fichier au dépôt, par exemple un fichier .txt avec une phrase de votre choix. Ajoutez-le à l'index et enregistrez-le dans le dépôt. Regardez l'historique de votre dépôt avec la commande git log. Effectuez une modification sur le fichier README.md et enregistrez-la dans le dépôt. Regardez l'historique de votre dépôt avec la commande git log.

Observation de l'historique

Vous connaissez déjà la commande git log qui affiche l'historique des commits. On peut observer les changements apportés par un commit particulier avec la commande git diff.

git diff <AAAA> <BBBB> où <AAAA> et <BBBB> sont les premières lettres des identifiants des commits à comparer. Par exemple : git diff 6abc87 2bf521.

Utilisation d'un dépôt distant

Un dépôt distant est un dépôt Git hébergé sur un serveur distant (GitHub, GitLab, Bitbucket, ...). Pour le projet et le TP nous utiliserons celui hébergé sur les serveurs de l'UCLouvain (https://forge.uclouvain.be/). L'UCLouvain ne permet pas aux externes de créer des dépôts, et donc des forks. Pour les besoins du TP les étudiants externes doivent créer un compte sur https://www.gitlab.com, mais devraient également demander un compte sur la forge UCLouvain car le projet doit se faire sur la forge UCLouvain.

Avertissement

Les étudiants UCLouvain doivent utiliser le bouton en bas à droite pour se connecter via l'authentification UCLouvain.

Si vous êtes externes à l'UCLouvain, ou si vous vous êtes enregistrés avant d'avoir lu les instructions sans utiliser l'authentification UCLouvain l'université doit valider votre compte. En attendant, vous pouvez utiliser gitlab.com qui fonctionne plus ou moins de la même façon pour faire le TP. Le projet doit cependant se faire obligatoirement sur la forge.

Un dépôt local peut être lié à un dépôt distant. Git permet de synchroniser les deux dépôts en copiant les commits de l'un à l'autre. Un dépôt peut être public et donc accessible à tous, ou privé.

Création d'un dépôt distant

Connectez-vous sur le GitLab de l'UCL : https://forge.uclouvain.be/ en utilisant l'authentification UCLouvain en bas à droite.

GitLab Login

Créez un nouveau projet en cliquant sur le bouton "New project". Vous devriez voir une page comme celle illustrée par l'image ci-dessous. Sur cette page, sélectionnez "Create blank project". Laissez l'initialisation du projet avec un fichier README.md.

GitLab, image du bouton create project

Configurez le projet en indiquant le nom du projet, la description et le type de projet (pour le TP, publiez-le en privé).

GitLab, configuration du projet

Si votre projet est correctement configuré, vous devriez obtenir une page comme celle illustrée par l'image ci-dessous.

GitLab, intialization du projet

Comme demandé, le dépôt est initialisé avec un fichier README. Le README est un fichier texte qui contient des informations sur le projet. L'extension .md signifie qu'il est au format Markdown. C'est un standard qui définit quelques moyens de mettre en forme le texte, un peu comme le HTML. Prenez le temps d'écrire quelques lignes.

Clonage d'un dépôt distant

Pour créer une copie locale du dépôt distant, on utilise la commande git clone.

Exemple : git clone https://forge.uclouvain.be/votre_pseudo/my-project.git

L'image ci-dessous vous indique comment trouver l'adresse du dépôt distant. Choisissez "Clone with HTTPS" et copiez l'adresse.

GitLab, cloner un projet

Créez un nouveau répertoire et clonez le dépôt distant que vous avez créé à l'exercice précédent (https://forge.uclouvain.be/votre_pseudo/my-project ). Un nouveau dossier devrait être créé avec les fichiers du dépôt. Dans la copie locale obtenue par le clone, les commits se feront toujours localement, on navigue dans l'historique local. Mais on synchronise le dépôt distant avec les commandes git push et git pull.

Modification du dépôt

Modifiez le fichier README.md qui a été cloné avec votre éditeur de texte préféré, comme gedit, thonny ou même pycharm.

Enregistrez ensuite les modifications dans le dépôt local:

$ git add README.md
$ git commit

La dernière commande, git commit ouvrira un éditeur de texte. Par défaut c'est souvent vim, un éditeur de texte en ligne de commande avec des symboles tildes ~ comme sur l'image ci-dessous. Si vous êtes perdu avec vim, consultez la documentation INGI.

vim

Entrez d'abord un titre de maximum 80 caractères, puis une ligne vide, et finalement une description claire, nette et précise.

Pour quitter VIM il faut appuyer la touche ESC et entrer :q suivi de la touche ENTER.

Une alternative au git add est d'utiliser directement git commit --interactive tel que vu en cours.

Synchronisation avec un dépôt distant

Ensuite synchronisez votre dépôt local avec votre dépôt distant en faisant git push.

Sur la Forge, vous devriez pouvoir observer vos modifications. Vous pouvez également visualiser ce commit en ligne, et voir le contenu d'un fichier sur la Forge.

Cliquez sur le fichier README.md que vous venez de modifier. Vous aurez une visualisation en ligne du fichier comme celle-ci :

GitLab, editer en ligne

Cliquez sur le bouton "Edit" afin de modifier le fichier en ligne :

GitLab, editer en ligne

Vous pouvez ajouter une phrase, et de la même façon entrer une description commençant par un titre, une ligne vide et puis la description.

Cliquez sur "commit change".

Avertissement

NE JAMAIS MODIFIER DU CODE EN LIGNE !!!

Il convient de toujours tester votre code avant de le publier sur le dépôt commun. Seuls le texte ou des commentaires peuvent être modifiés en ligne. Si vous modifiez du code en ligne, ce sera la preuve que vous êtes très peu consciencieux et cela sera pénalisé. Imposer à vos condisciples de vérifier votre code à votre place est un acte lâche qui attirera assurément des remontrances de vos collègues.

Il faut maintenant récupérer le contenu de la modification distante dans votre dépôt local :

$ git pull

Travailler à plusieurs sur un dépôt distant

Avertissement

Remarque : les exercices suivants sont à faire en groupes de 2 ou 3 personnes.

Formez maintenant des groupes de 2 ou 3 personnes et désignez un dépôt distant sur lequel vous allez travailler à plusieurs. Les autres peuvent supprimer leurs dépôts de test.

Le propriétaire du dépôt distant doit ajouter les autres membres du groupe. Pour cela, le propriétaire du Git doit aller dans le menu à gauche sur Gitlab et cliquer sur "Project informations" et ensuite "Members". Vous devriez voir une page comme celle illustrée ci-dessous. Sur cette page, le propriétaire doit ajouter les autres personnes du groupe en tant que "Developer".

GitLab issues

Quand vous obtenez les accès, clonez localement ce dépôt distant comme vous aviez fait précédemment.

Un·e membre de votre groupe crée des modifications dans le dépôt local et les synchronise du dépôt local vers le dépôt distant. Les autres personnes du groupe doivent synchroniser leur dépôt avec la commande appropriée.

Tou·te·s les membres du groupe devraient avoir les mêmes modifications dans leur dépôt local.

Pour vous en assurer vous pouvez utiliser git log et vérifier que l'id du dernier commit est bien la même chez tout le monde.

Modifications simultanées sur deux fichiers différents

En même temps, un·e membre du groupe modifie le fichier README.md. Une· autre membre du groupe crée un fichier main.py. Les deux membres du groupe qui ont apporté les modifications synchronisent leurs dépôts avec le dépôt distant. Quel est le résultat ?

Le push du deuxième membre du groupe échoue, car il faut être à jour avec le dépôt distant. Il y a un conflit, car vous avez modifié le dépôt en même temps.

Comme vous avez modifié des fichiers différents, tout devrait bien se passer. La·le deuxième membre qui n'a pas pu pousser ses modifications doit simplement faire git pull --rebase pour appliquer ses modifications au-dessus des modifications du premier à pousser. Après cela, comme git a rebasé ses modifications sur celle du premier, vous pouvez faire git push sans soucis.

Modifications simultanées à deux endroits différents d'un même fichier

Assurez-vous avant cet exercice que le fichier README.md fait plusieurs lignes avec un texte bidon, et que tou·te·s les membres ont bien exécuté git pull. Un·e membre du groupe modifie la première ligne du fichier README.md. Un·e autre membre du groupe modifie une ligne différente du fichier README.md, par exemple la ligne numéro 5. Les deux membres du groupe qui ont apporté les modifications synchronisent leurs dépôts avec le dépôt distant. Quel est le résultat ?

Comme dans l'exercice précédent, le deuxième ne peut pas pousser ses modifications. Cependant git pull --rebase fonctionne toujours, car git est assez puissant que pour fusionner des modifications dans le même fichier qui ne sont pas faites au même endroit. Il faut en général une ligne d'écart pour que les choses se passent correctement.

Modifications simultanées aux mêmes endroits

Deux membres du groupe modifient la même ligne du fichier README.md. Les deux personnes synchronisent leurs dépôts avec le dépôt distant. Quel est le résultat ?

Cette fois, comme vous avez modifié le même fichier au même endroit, git pull --rebase va échouer:

$ git pull --rebase
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 418 bytes | 418.00 KiB/s, done.
From forge.uclouvain.be:XXX/YYY
   adb1137..09709a5  main       -> origin/main
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply d70f38d... My commit
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply d70f38d... My commit

Git vous invite à résoudre le conflit et à faire un commit de cette résolution.

Vous avez deux solutions: corriger manuellement le conflit, ou utiliser un éditeur de texte supportant la fusion de document, tel que meld.

Manuellement

On doit pour cela ouvrir le fichier incriminé avec un éditeur de fichier texte. Les zones en conflit sont marquées par des chevrons ajoutés par Git.

# Readme of the project

<<<<<<< HEAD
The modification of the first member
=======
The modification of the second member
>>>>>>> d70f38d (My commit)

La première version est celle de celui qui a modifié le fichier en premier. La seconde est la différence locale.

Vous pouvez corriger le fichier en enlevant bien les chevrons et tout texte superflu. Ensuite, marquez le fichier comme corrigé en l'ajoutant à l'index comme d'habitude avec git add.

Attention ! pour continuer le rebasage, faites git rebase --continue.

À l'aide d'un éditeur

Alors qu’un git pull --rebase vient d'échouer, lancez la commande git mergetool.

Si la commande ne lance vimdiff ou un outil qui ne vous convient pas, installez le logiciel meld. Si git mergetool ne lance toujours pas meld, utilisez git mergetool --tool=meld. Sur Windows, si cela ne fonctionne toujours pas, suivez les conseils de cet article sur stackoverflow.

Meld

La fenêtre de meld vous montre à gauche le fichier local, au milieu la version finale, et à droite la version distante.

Le jeu consiste à envoyer les modifications vers le centre. La ligne verte a été ajoutée seulement d'un côté et est donc simple à ajouter au milieu. Il suffit de cliquer sur la flèche pointant vers le centre.

La ligne rouge a été modifiée à droite et à gauche, vous devez choisir laquelle est la bonne, ou vous-même écrire une nouvelle version qui contente tout le monde.

Enregistrez et quittez lorsque vous avez fusionné toutes les modifications.

git mergetool va ouvrir tous les fichiers en conflit les uns après les autres. Une fois terminé, vous pouvez faire git push.

Fusion

Le rebasage est plus propre que la fusion. En effet, git rebase va reprendre les différences locales depuis l'historique commun avec la branche distante, et les réappliquer sur la version distante. C'est plus propre, car le résultat final sera équivalent à un cas où l'utilisateur local aurait écrit son code après avoir récupéré la dernière version du code. Préférez donc l'utilisation du rebasage tel que vu ci-dessus pour gérer les conflits plutôt que la fusion (git merge). La fusion va fusionner deux branches, il restera donc en ligne deux "histoires" indépendantes. Pour comprendre l'historique du projet, un lecteur devra remonter votre branche locale et la distante et comprendre comment elles ont été fusionnées. Dans le cas d'un rebasage, elles apparaitront comme venant l'une après l'autre.

Les branches

Dans certaines situations, il est utile de travailler sur plusieurs versions d'un même projet en parallèle. Par exemple, on peut vouloir travailler sur une nouvelle fonctionnalité sans modifier la version stable du projet. Ces versions peuvent parfois être fusionnées (mais pas forcément).

Notions fondamentales

  • Une branche est une lignée de commits à laquelle on a donné un nom.

  • Le commit le plus récent d'une branche est appelé sommet (en anglais : tip).

  • La copie de travail est en général liée au sommet d'une branche (main, ou anciennement master par défaut).

  • A chaque nouveau commit, le sommet de la branche courante est avancé vers ce nouveau commit (la branche « pousse »).

Voici quelques commandes utiles pour l'exercice suivant:

  • Pour créer une nouvelle branche, on utilise la commande "git branch" : git branch nom_de_la_branche

  • Pour basculer sur une branche, on utilise la commande "git checkout" : git checkout nom_de_la_branche

Création d'une nouvelle branche

Créez une nouvelle branche my_first_branch et basculez sur cette nouvelle branche.

Exécutez la commande git branch pour vérifier que vous êtes bien sur la branche my_first_branch.

Synchronisez la branche my_first_branch avec le dépôt distant à l'aide de la commande git push origin my_first_branch .

Apportez une modification localement au fichier README.md sur la branche my_first_branch et synchronisez la branche avec le dépôt distant. Pour le push utilisez la commande git push origin my_first_branch

Normalement, vous devriez pouvoir voir vos deux branches sur le dépôt distant comme sur l'image ci-dessous (en cliquant sur le lien "Branches").

GitLab issues

Mettez à jour la branche main avec les modifications de la branche my_first_branch.

Basculez sur votre branche principale main. Mettez à jour la branche my_first_branch avec la branche main à l'aide de la commande git FG <nom de la branche>.

Les Forks et les Merge Requests

Forker un dépôt distant

Le fork est une copie d'un dépôt distant. Il permet de travailler sur un projet sans avoir les droits d'écriture sur le dépôt distant.

Commencez par changer la permission du dépôt distant que vous aviez créé au début de ce tutoriel pour la mettre en public. Cela permettra à vos camarades de groupe de pouvoir forker ce dépôt. Vous devriez trouver cette option dans le menu "Settings" du dépôt distant. L'image ci-dessous montre où se trouve cette option dans le menu Settings.

GitLab permissions

Forkez le dépôt distant de vos camarades de groupe et clonez-le sur votre machine.

GitLab fork

Ajoutez des modifications à un fichier de votre choix (le fichier README.md par exemple) et synchronisez le dépôt local avec le dépôt distant.

Le but de l'exercice suivant sera d'"envoyer" vos modifications au dépôt distant de votre camarade de groupe à l'aide d'une "merge request".

Merge request

Une "merge request" (ou aussi appelée "pull request") est une demande de fusion de modifications d'une branche vers une autre branche.

Dans l'exercice suivant, vous allez faire une merge request depuis le dépôt que vous avez forké vers le dépôt distant de vos camarades de groupe.

Ensuite, faites une pull request sur le dépôt distant de vos camarades de groupe. Vous pouvez faire des merge request sur GitLab depuis l'interface web.

Cliquez sur Merge request et ensuite sur le bouton "New merge request" et sélectionnez la branche depuis laquelle vous avez fait vos modifications.

GitLab merge request

"Source branch" est la branche sur laquelle vous avez fait vos modifications (dans cet exercice, c'est depuis votre fork)

"Target branch" est la branche sur laquelle vous voulez faire vos modifications (vers le dépôt de vos camarades de groupe)

Cliquez sur "compare branches and continue" et ensuite sur "Create merge request".

Dans l'onglet "Changes" il peut voir les modifications que vous avez ajoutées. Pour accepter la merge request, cliquez sur le bouton "Merge".

GitLab

Le processus de vérification d'une Merge Request est appelé "faire une review". Le camarade a une lourde responsabilité : valider le changement (en général, le code) proposé par son collègue. Si le code introduit un problème, les deux sont tout autant responsables.

Quand votre camarade de groupe accepte votre merge request, son dépôt distant aura les modifications que vous avez apportées. Il pourra synchroniser ces modifications sur son dépôt local avec le distant avec l'habituel git pull.

Dans ce cours, vous êtes obligés d'utiliser des Merge Requests pour toutes modifications de la branche main!

Les issues

Les issues sont des tickets qui permettent de suivre les problèmes et les demandes de fonctionnalités d'un projet. Vous pouvez les créer sur GitLab depuis l'interface web.

Créez une issue sur le dépôt distant de vos camarades de groupe et ajoutez une description de l'issue.

GitLab issues

L'image ci-dessous illustre la configuration d'une issue que vous devriez remplir. Vous devez ajouter un titre avec une description du problème (dans le cadre de description).

GitLab issues

Remplissez les champs et cliquez sur "Create issue".

Dans cet issue, taguez l'assistant qui vous encadre en utilisant "@" et en tapant les premières lettres de son pseudo ou son login. Lorsqu'il aura répondu, fermez l'issue.

Utiliser Git dans PyCharm. (optionnel)

Utilisez PyCharm pour ouvrir le projet my-project qui a été créé précédemment. Modifiez le fichier README.md.

Vous constatez que le fichier README.md est en bleu dans l'explorateur de fichiers. Cela signifie que le fichier a été modifié, mais n'a pas encore été ajouté au dépôt local.

PyCharm

Cherchez dans le menu PyCharm "Git" et sélectionnez "Commit".

PyCharm commit

Un menu s'ouvre (illustré ci-dessous).

PyCharm commit

Dans l'encadré Commit Message vous devez ajouter un message pour le commit. Dans l'encadré supérieur, vous pouvez voir les fichiers qui ont été modifiés.

Cliquez sur le bouton "Commit" pour faire le commit. Pour synchroniser le dépôt local avec le dépôt distant, cliquez sur le bouton "Push" dans le menu "Git".

La première fois que vous faites un push depuis Pycharm, vous devez entrer votre nom d'utilisateur et votre mot de passe pour vous authentifier sur Gitlab.

GitLab issues

Pour "pull" les modifications du dépôt distant, cliquez sur le bouton "Pull" dans le menu "Git".

Fin du tutoriel

Vous avez terminé ce tutoriel sur Git. C'est l'occasion de commencer la partie git de votre projet phase 1 !