.. _misc-02-git: Git === Git est le logiciel de gestion de versions décentralisé le plus utilisé pour le développement informatique. Il permet de synchroniser les contenus d'une (ou plusieurs) machine locale et d'un dépôt distant. .. image:: images/misc-02-git-fig-01.png :width: 75 % :align: center On peut en avoir une utilisation plus ou moins avancée : - un seul développeur : l'utilisation standard permet d'enregistrer les différentes versions d'un projet et de les synchroniser avec un dépôt distant (Git ESIEE, GitHub, BitBucket, ...) ; - plusieurs développeurs : maintient une version centralisée du projet et permet à plusieurs personnes de contribuer au développement, chacun ayant une version à jour du code sur sa machine locale. Installation ------------ Windows 11 .......... Git n'est pas installé par défaut. Il doit être installé depuis `cette page `_. .. image:: images/misc-02-git-fig-02.png :width: 75 % :align: center Il est ensuite disponible dans un terminal Git Bash que l'on trouve dans le menu Démarrer:: $ git --version git version 2.38.1.windows.1 La version peut varier. Linux et MacOS .............. Git est installé par défaut et accessible directement dans le terminal standard :: $ git --version git version 2.38.0 La version peut varier. .. _creer-un-repertoire-local: Créer un répertoire local ------------------------- On crée un répertoire local destiné à héberger les fichiers du projet :: $ mkdir myproject Pour créer un contenu minimal, éditer un fichier :file:`README.md` avec uniquement le titre du projet. .. _creer-un-repo-distant: Créer un repo distant --------------------- Pour synchroniser son travail entre la machine locale et le repo distant, il faut disposer d'un compte sur une plateforme. Pour les élèves de l'ESIEE, un compte est déjà créé sur `https://git.esiee.fr `_. .. image:: images/misc-02-git-fig-03.png :width: 75 % :align: center Il faut ensuite créer le repo distant proprement dit : #. New project #. Create blank project #. Project name : myproject #. Visibility level : Public #. **DON'T** Initialize repository with a README puis exécuter les instructions : - de la section "Git global setup" ; - et de la section "Push an existing folder" en utilisant le répertoire local créé à l'étape précédente. .. warning:: Sur une autre plateforme, `GitHub `_ par exemple, la procédure est similaire même si les termes peuvent varier. Maintenant on dispose d'un répertoire local synchronisé avec un repo distant. Recharger la page du projet sur la plateforme distante. Le fichier :file:`README.md` créé à l'étape précédente doit maintenant être présent. Forker un projet ---------------- Chaque utilisateur dispose de son propre espace distant. .. image:: images/misc-02-git-fig-04.png :width: 75 % :align: center Un utilisateur peut héberger plusieurs repos dans son espace. .. image:: images/misc-02-git-fig-05.png :width: 75 % :align: center Si un repo est public, on peut le copier dans son espace distant avec un *fork*. .. image:: images/misc-02-git-fig-06.png :width: 75 % :align: center Ici, Lazare Garçin se rend sur la page public du repo ``myproject`` de Adam Labrosse, s'identifie, et *fork* le projet. Il dispose ensuite d'une copie exacte du projet dans son propre espace. Cloner un projet ---------------- Le **fork** est une copie d'un repo distant vers un espace distant. L'opération permettant de copier un repo distant sur une machine locale est un **clonage**. .. image:: images/misc-02-git-fig-07.png :width: 75 % :align: center On peut cloner sur sa machine : - les repos dont on est propriétaire ; - les repos publics. Dans chaque cas, une procédure d'authentification est déclenchée. Il y a 2 alternatives. - l'authentification ``https`` ne nécessite aucune opération supplémentaire mais le login/password est demandée à chaque transaction:: $ git clone https://git.esiee.fr/labrossa/myproject.git - l'authentification ``ssh`` nécessite un paramétrage (`génération de clés SSH `_ et `ajout au compte Gitlab `_), mais elle est ensuite réalisée automatiquement par comparaison des clés locales et distantes:: $ git clone git@git.esiee.fr:labrossa/myproject.git .. _synchroniser-son-travail-avec-le-repo-distant: Synchroniser son travail avec le repo distant --------------------------------------------- Tout au long de la vie du projet, vous pouvez être amenés à utiliser plusieurs machines de développement (des machines différentes dans les salles de l'ESIEE, votre machine personnelle, etc...). Si vous maintenez la synchronisation entre repo distant et repo local, vous pourrez disposer à tout moment de la dernière version de votre travail. Vous pouvez utiliser :command:`git`, depuis le terminal ou depuis Visual Studio Code, pour maintenir la synchronisation entre votre répertoire local et votre repo distant. .. image:: images/misc-02-git-fig-08.png :width: 75 % :align: center Avant une phase de développement, on récupére les modifications depuis le repo distant avec la commande:: $ git pull Lorsqu'une nouvelle fonctionnalité est implémentée : - on ajoute les fichiers du répertoire à l'index :: $ git add . - on enregistre les modifications dans le repo local avec un message explicatif:: $ git commit -m "ajout d'une interface graphique" - on pousse les modifications de la machine locale vers le repo distant :: $ git push origin master .. warning:: Ne pas oublier de pusher votre travail à chaque étape significative du projet. .. _travail-collaboratif: Travail collaboratif -------------------- Un projet informatique implique généralement plusieurs contributeurs et il est primordial de disposer d'une version à jour du travail effectué par chacun. Git est très efficace dans ce domaine. .. image:: images/misc-02-git-fig-09.png :width: 75 % :align: center Un prérequis est que le propriétaire du repo distant (Adam Labrosse dans ce cas) invite l'autre développer en lui donnant les droits nécessaires (Developer). Sur la plateforme `https://git.esiee.fr `_:: Project Information > Members > Invite members 1. une version v1 du projet est développée par Adam Labrosse et incluse dans le repo local ; 2. le repo local est transféré vers le repo distant ; 3. Lazare Garçin n'a pas encore contribué au projet. Il récupère le travail de Adam Labrosse en *clonant* le projet ; 4. il produit une version v2 en apportant des modifications au projet ; 5. puis ajoute ses fichiers à l'index ; 6. les inclut dans le repo local ; 7. et transfère son repo local modifié vers le repo distant ; 8. Lazare Garçin récupère la dernière version du repo et dispose maintenant de la v2 sur sa machine. .. warning:: Sur une autre plateforme, `GitHub `_ par exemple, la procédure est similaire même si les termes peuvent varier. Utilisation plus avancée ------------------------ Git a été utilisé jusqu'à présent de façon basique avec en particulier une seule branche de développement. Pour un projet complexe, on peut mettre en oeuvre un développement sur plusieurs branches. .. image:: images/misc-02-git-fig-10.png :width: 75 % :align: center Chaque disque représente un *commit* et chaque couleur, une branche différente, indépendante des autres, permettant de développer des fonctionnalités nouvelles sans impacter le projet qui reste toujours dans une version stable. On peut se familiariser avec la gestion des branches avec `Learn Git Branching `_. Exercice -------- Ce travail est individuel. Il permet de simuler une collaboration entre deux utilisateurs, Alice et Bob, sur un projet Git. Chaque élève joue ici le rôle d'Alice. .. warning:: L'ordonnancement des étapes est strict. Il est impératif de suivre rigoureusement les étapes dans l'ordre indiqué pour éviter les conflits et les erreurs de synchronisation. Les ``id`` des commits sont donnés à titre indicatif et peuvent varier d'une machine à l'autre. Créer un répertoire dédié à cet exercice et se positionner dedans :: $ mkdir git-playground $ cd git-playground Tout le travail sera réalisé dans ce répertoire. A terme, il contiendra : - un repo central (pour simuler un repo distant) et permettre l'échange d'informations entre Alice et Bob ; - un répertoire de travail pour Alice, dont le repo local sera associé et synchronisé au repo central ; - un répertoire de travail pour Bob, dont le repo local sera associé et synchronisé au même repo central. Il est important de souligner que l'échange d'informations entre Alice et Bob se fait uniquement par le biais du repo central. Ils ne peuvent pas accéder directement aux répertoires de travail de l'autre. .. note::Notes - les interactions reproduites ci dessous se passent sur le compte de ``alice``, mais elles pourraient tout aussi bien se passer sur le compte de `bob` ; - les sorties des commandes peuvent différer légèrement de celles que vous obtiendrez sur votre machine. @@@@ Création du repo central ........................ Pour simuler le repo distant, on crée un repo ``bare`` sur le disque local. Ce repo possédera toutes les propriétés d'un vrai repo distant. Son caractère local simplifiera les interactions :: ~/git-playground $ git init --bare exercice-git.git Initialized empty Git repository in ~/git-playground/exercice-git.git/ hint: Using 'master' as the name for the initial branch. This default branch name hint: is subject to change. To configure the initial branch name to use in all hint: of your new repositories, which will suppress this warning, call: hint: hint: git config --global init.defaultBranch hint: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and hint: 'development'. The just-created branch can be renamed via this command: hint: hint: git branch -m Ce repo est créé vide, comme le précise le message de confirmation. Il n'y a pas de branche, pas de commit, pas de fichier. Il est prêt à recevoir des contributions. .. image:: images/misc-02-git-fig-11.png :width: 20 % :align: center Il apparait comme un répertoire dans le système de fichiers, mais il ne contient pas de fichiers visibles. Il est organisé pour stocker les objets Git (commits, blobs, etc.) et les références (branches, tags, etc.) :: ~/git-playground $ cd exercice-git.git ~/git-playground/exercice-git.git $ ls -la total 40 drwxrwxr-x 7 alice alice 4096 Jul 6 20:13 . drwxrwxr-x 3 alice alice 4096 Jul 6 20:13 .. drwxrwxr-x 2 alice alice 4096 Jul 6 20:13 branches -rw-rw-r-- 1 alice alice 66 Jul 6 20:13 config -rw-rw-r-- 1 alice alice 73 Jul 6 20:13 description -rw-rw-r-- 1 alice alice 23 Jul 6 20:13 HEAD drwxrwxr-x 2 alice alice 4096 Jul 6 20:13 hooks drwxrwxr-x 2 alice alice 4096 Jul 6 20:13 info drwxrwxr-x 4 alice alice 4096 Jul 6 20:13 objects drwxrwxr-x 4 alice alice 4096 Jul 6 20:13 refs .. important:: Le repo distant constitue le référentiel unique du projet, en ce sens qu'il est l'espace opérationnel du projet. Dit autrement, le projet n'existe que par les fichiers qu'il contient dans le repo distant. @@@@ Alice clone le repo (1) ....................... Un clone est la copie conforme d'un repo. Ici Alice va cloner le repo central, ce qui lui permettra de travailler dans un répertoire dédié. Elle clone le repo central avec la commande `git clone` en spécifiant l'URL du repo distant (ici, le chemin local) :: ~/git-playground/exercice-git.git $ cd .. ~/git-playground $ git clone exercice-git.git alice-exercice-git Cloning into 'alice-exercice-git'... warning: You appear to have cloned an empty repository. done. .. image:: images/misc-02-git-fig-12.png :width: 50 % :align: center .. important:: Cette opération ne doit être réalisée qu'une seule fois, au début du projet. Si elle est répétée, le contenu du repo local sera écrasé par le repo central qui n'est vraisemblablement pas dans le même état. Maintenant le repo cloné est disponible sous la forme d'une copie parfaite du repo initial stocké dans un répertoire de travail dans lequel Alice va pouvoir ajouter des fichiers :: ~/git-playground $ ls -la total 16 drwxrwxr-x 4 alice alice 4096 Jul 6 20:14 . drwxrwxr-x 7 alice alice 4096 Jul 6 20:13 .. drwxrwxr-x 3 alice alice 4096 Jul 6 20:14 alice-exercice-git drwxrwxr-x 7 alice alice 4096 Jul 6 20:13 exercice-git.git Le repo proprement dit est hébergé dans le répertoire de travail dans un sous-répertoire caché. Le dossier caché ``.git`` est le répertoire qui confère à ce répertoire de travail un statut particulier pour Git. Il contient les informations nécessaires pour suivre l'historique des modifications, les branches, les commits, etc. Il contient également la configuration. Immédiatement après le clone, le répertoire ``.git`` est identique à celui du repo distant, car le clone crée une copie exacte de l'état du repo :: git-playground $ cd alice-exercice-git git-playground/alice-exercice-git (master) $ ls -la total 0 drwxr-xr-x 1 user 1049089 0 juil. 3 15:27 ./ drwxr-xr-x 1 user 1049089 0 juil. 3 15:27 ../ drwxr-xr-x 1 user 1049089 0 juil. 3 15:27 .git/ ``master`` est précisé avant le prompt. Il s'agit de la branche (par défaut) créée par Git. On verra ultérieurement comment travailler avec plusieurs branches. .. note:: Par abus de langage, mais pour simplifier les choses, on appellera indifféremment repo : - le repo au sens strict, hébergé dans le dossier ``.git`` (définition stricte), - mais également tout répertoire de travail contenant un dossier ``.git``. Le repo au sens large est donc la co existence des 3 espaces de travail vus plus haut : - le répertoire de travail, qui contient les fichiers du projet. C'est le répertoire que l'on voit dans l'explorateur de fichiers ; - l'index, qui est une zone intermédiaire entre le répertoire de travail et l'historique. C'est une sorte de zone de préparation avant l'enregistrement des modifications dans l'historique ; - le repo au sens strict, qui est la liste des commits effectués sur le projet. Un commit est une photographie instantanée de l'état du projet à un moment donné. Il est identifié par un hash unique. @@@@ Alice configure son identité ............................ Avant de commencer à travailler, Alice doit configurer son identité dans le repo local. Cela permet d'associer ses commits à son nom et son adresse e-mail. Par défaut, la configuration locale :: ~/git-playground/alice-exercice-git (master) $ git config --local --list core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true remote.origin.url=~/git-playground/exercice-git.git remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master Pour le moment aucun utilisateur n'est associé à ce repo. Alice doit définir son nom et son adresse e-mail :: ~/git-playground/alice-exercice-git (master) $ git config user.name "alice" ~/git-playground/alice-exercice-git (master) $ git config user.email "alice@esiee.fr" On vérifie que la configuration a bien été prise en compte :: ~/git-playground/alice-exercice-git (master) $ git config --local --list core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true remote.origin.url=~/git-playground/exercice-git.git remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master user.name=alice user.email=alice@esiee.fr .. note:: Il est important de configurer son identité avant de commencer à travailler sur un repo Git. Cela permet d'associer les commits à l'utilisateur et de garder une trace des contributions. Il est même possible que Git refuse de créer un commit si l'identité n'est pas configurée. @@@@ Alice crée un fichier ..................... Alice ajoute de l'information dans son répertoire de travail. Elle crée un fichier texte `cr.txt` et y écrit le début de la fable de La Fontaine "Le Corbeau et le Renard" :: ~/git-playground/alice-exercice-git (master) $ echo "Le corbeau et le renard" >> cr.txt .. note:: Ici, pour la clarté du propos, la commande `echo` permet d'écrire simplement du texte dans un fichier. Le processus normal consiste à faire appel à un éditeur de texte ou un environnement de développement comme VS Code. On peut vérifier que le fichier a bien été créé en listant les fichiers du répertoire de travail :: ~/git-playground/alice-exercice-git (master) $ ls -la total 16 drwxrwxr-x 3 alice alice 4096 Jul 6 20:18 . drwxrwxr-x 4 alice alice 4096 Jul 6 20:14 .. -rw-rw-r-- 1 alice alice 24 Jul 6 20:18 cr.txt drwxrwxr-x 7 alice alice 4096 Jul 6 20:17 .git On peut également contrôler la validité du contenu du fichier :: ~/git-playground/alice-exercice-git (master) $ cat cr.txt Le corbeau et le renard .. image:: images/misc-02-git-fig-13.png :width: 50 % :align: center On vérifie que le fichier est "détecté" par git mais pas encore ajouté au repo. C'est le sens du caractère ``??`` :: ~/git-playground/alice-exercice-git (master) $ git status -s ?? cr.txt @@@@ Alice ajoute le fichier à son repo local (2) ............................................ Le repo local est une structure de données distinctes du répertoire de travail. Pour rappel elle est stockée dans le sous-répertoire caché ``.git``. Le répertoire de travail contient les fichiers que l'on peut voir et modifier, tandis que le repo local contient l'historique des modifications, les branches, les commits, etc. Pour le moment, rien n'a été ajouté à l'index (staging area) de Git. L'index est une zone intermédiaire où les modifications sont préparées avant d'être enregistrées dans l'historique du repo local. Il permet de sélectionner les modifications à inclure dans le prochain commit. On observe le contenu de l'index avec la commande :: ~/git-playground/alice-exercice-git (master) $ git ls-files --stage ~/git-playground/alice-exercice-git (master) $ Pour que le fichier ``cr.txt`` soit pris en dans le repo, Alice doit l'ajouter à l'index (staging area) avec la commande ``git add`` :: ~/git-playground/alice-exercice-git (master) $ git add . Maintenant, si on vérifie l'état du repo, on constate que le fichier ``cr.txt`` fait partie des fichiers suivis par Git (mais pas encore commités) :: ~/git-playground/alice-exercice-git (master) $ git status -s A cr.txt Et l'index reflète maintenant cette opération :: ~/git-playground/alice-exercice-git (master) $ git ls-files --stage 100644 d8b1220cc7f638af1d2de695d775f14c68a826be 0 cr.txt Aucun commit n'a été effectué, et l'historique est vide :: ~/git-playground/alice-exercice-git (master) $ git log Command failed with exit code 128 fatal: your current branch 'master' does not have any commits yet Puisque le fichier a été ajouté à l'index, il est prêt à être commité, c'est à dire inscrit dans l'historique. L'opération de commit doit être accompagnée d'un message décrivant les modifications apportées :: ~/git-playground/alice-exercice-git (master) $ git commit -m "create le corbeau et le renard" [master (root-commit) 033c477] create le corbeau et le renard 1 file changed, 1 insertion(+) create mode 100644 cr.txt Le commit est maintenant enregistré dans le repo local. On peut vérifier l'état du repo :: ~/git-playground/alice-exercice-git (master) $ git status -s nothing to commit, working tree clean et le contenu de l'historique :: ~/git-playground/alice-exercice-git (master) $ git log commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard .. image:: images/misc-02-git-fig-14.png :width: 50 % :align: center Maintenant, les modifications apportées au fichier `cr.txt` sont bien dans l'historique du repo local et le message "nothing to commit, working tree clean" indique que le répertoire de travail est à jour par rapport à l'historique. .. note:: Git construit les commit par différence entre l'état du répertoire de travail avant et après le commit. Il n'enregistre pas le contenu complet du fichier, mais seulement les modifications apportées. @@@@ Alice pousse ses modifications vers le repo distant (3) ....................................................... Alice doit maintenant synchroniser ses modifications avec le repo central pour que Bob puisse les voir. Elle n'a pas besoin de spécifier l'adresse du repo distant, car elle a déjà été configurée lors du clonage :: ~/git-playground/alice-exercice-git (master) $ git config --get remote.origin.url ~/git-playground/exercice-git.git La commande ``git push`` envoie les commits de la branche courante du repo local vers la branche correspondante du repo central :: ~/git-playground/alice-exercice-git (master) $ git push Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 8 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 434 bytes | 28.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 To //files/user/git-playground/exercice-git.git * [new branch] master -> master .. image:: images/misc-02-git-fig-15.png :width: 50 % :align: center On peut vérifier l'état du repo central en utilisant la commande ``git log`` avec l'option ``--git-dir`` pour spécifier le chemin du repo distant :: ~/git-playground/alice-exercice-git (master) $ git --git-dir=../exercice-git.git log commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard On peut voir ainsi la liste des commits dans le repo central (qui contient pour le moment le seul commit d'Alice). Chacun est décrit par - son identifiant (hash) ; - la branche sur laquelle il se trouve ; - son auteur ; - son adresse e-mail ; - et le message associé. @@@@ Alice modifie le fichier (4) et (5) ................................... Alice décide de continuer à travailler sur le fichier ``cr.txt`` :: ~/git-playground/alice-exercice-git (master) $ echo "" >> cr.txt ~/git-playground/alice-exercice-git (master) $ echo "Maitre Corbeau sur son arbre perché" >> cr.txt Le fichier reflète bien les modifications apportées :: ~/git-playground/alice-exercice-git (master) $ cat cr.txt Le corbeau et le renard Maitre Corbeau sur son arbre perché On peut vérifier que la modification n'a pas échappé à Git, c'est le sens du caractère ``M`` :: ~/git-playground/alice-exercice-git (master) $ git status -s M cr.txt Pour visualiser la différence entre l'état du fichier avant et après la modification :: ~/git-playground/alice-exercice-git (master) $ git diff diff --git a/cr.txt b/cr.txt index d8b1220..7608325 100644 --- a/cr.txt +++ b/cr.txt @@ -1 +1,3 @@ Le corbeau et le renard + +Maitre Corbeau sur son arbre perché L'information fournie ici est dense. - ``diff --git a/cr.txt b/cr.txt`` indique qu'il y a une différence entre deux versions du fichier ``cr.txt`` : - ``a/cr.txt`` : version du dernier commit (HEAD) - ``b/cr.txt`` : version du répertoire de travail (modifiée) - ``index d8b1220..7608325 100644`` indique les informations sur le fichier : - ``d8b1220`` est le hash SHA-1 du commit précédent (HEAD) - ``7608325`` est le hash SHA-1 du fichier modifié - ``100644`` est le mode d'accès du fichier, indiquant qu'il s'agit d'un fichier normal avec des permissions standard. - ``--- a/cr.txt`` et ``+++ b/cr.txt`` indiquent les versions du fichier : - ``--- a/cr.txt`` : la version "ancienne" du fichier (celle du repo, HEAD) - ``+++ b/cr.txt`` : la version "nouvelle" (celle modifiée dans le répertoire de travail) - ``@@ -1 +1,3 @@`` indique le contexte de la modification et identifie le "hunk" (bloc de changement): - ``-1`` = à partir de la ligne 1 dans l'ancienne version - ``+1,3`` = ligne 1, et maintenant il y a 3 lignes au lieu d'une seule - Les lignes suivantes montrent les différences : - ``Le corbeau et le renard`` : ligne inchangée - ``+`` : ligne vide ajoutée - ``+Maître Corbeau, sur un arbre perché`` : ligne ajoutée Une fois la modification effectuée, Alice ajoute le fichier à l'index (staging area) et effectue un commit :: ~/git-playground/alice-exercice-git (master) $ git add . ~/git-playground/alice-exercice-git (master) $ git commit -m "add cr verse 1" [master c752930] add cr verse 1 1 file changed, 2 insertions(+) Puis push vers le repo central :: ~/git-playground/alice-exercice-git (master) $ git push To ~/git-playground/exercice-git.git 033c477..c752930 master -> master .. image:: images/misc-02-git-fig-16.png :width: 50 % :align: center On peut vérifier l'état du repo local :: ~/git-playground/alice-exercice-git (master) $ git log commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard et celui du repo central (en précisant le chemin du repo distant) :: ~/git-playground/alice-exercice-git (master) $ git --git-dir=../exercice-git.git log commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard Ils sont bien tous les deux synchronisés. .. note:: Dans le travail collaboratif entre Alice et Bob, il est essentiel de garder l'ensemble des repos synchronisés. Chaque utilisateur doit régulièrement pousser ses modifications vers le repo central et récupérer les modifications des autres utilisateurs pour éviter les conflits. @@@@ Alice modifie une nouvelle fois le fichier (6) .............................................. Le travail sur un projet nécessite de nombreuses modifications. Alice décide de continuer à travailler sur le fichier ``cr.txt`` et ajoute un autre vers :: ~/git-playground/alice-exercice-git (master) $ echo "tenait en son bec un fromage." >> cr.txt C'est une bonne pratique de contrôler le bon déroulement de chacune des opérations :: ~/git-playground/alice-exercice-git (master) $ cat cr.txt Le corbeau et le renard Maitre Corbeau sur son arbre perché tenait en son bec un fromage. On fait apparaitre la différence entre le fichier modifié et le fichier du dernier commit :: ~/git-playground/alice-exercice-git (master) $ git diff diff --git a/cr.txt b/cr.txt index 7608325..8bd1c83 100644 --- a/cr.txt +++ b/cr.txt @@ -1,3 +1,4 @@ Le corbeau et le renard Maitre Corbeau sur son arbre perché +tenait en son bec un fromage. La bonne pratique est de réaliser l'opération ``add/commit/push`` pour chaque modification significative. Ici l'opération n'est pas spécialement significative, pour les besoins de la démonstration:: ~/git-playground/alice-exercice-git (master) $ git add . ~/git-playground/alice-exercice-git (master) $ git commit -m "add cr verse 2" [master afa888b] add cr verse 2 1 file changed, 1 insertion(+) ~/git-playground/alice-exercice-git (master) $ git push To ~/git-playground/exercice-git.git c752930..afa888b master -> master On vérifie l'état du repo local :: ~/git-playground/alice-exercice-git (master) $ git log commit afa888bba48d30a74d18116fd7a7e34f7091f5a4 Author: alice Date: Sun Jul 6 20:34:23 2025 +0200 add cr verse 2 commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard et par acquis de conscience, on vérifie également le repo central (en précisant le chemin du repo distant) :: ~/git-playground/alice-exercice-git (master) $ git --git-dir=../exercice-git.git log commit afa888bba48d30a74d18116fd7a7e34f7091f5a4 Author: alice Date: Sun Jul 6 20:34:23 2025 +0200 add cr verse 2 commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard pour constater qu'ils sont parfaitement synchronisés avec un empilement de 3 opérations. .. image:: images/misc-02-git-fig-17.png :width: 50 % :align: center @@@@ Voyager dans l'historique ......................... L'historique (obtenu avec ``git log``) est un empilement de photographies instantanées du projet à plusieurs moments dans le temps. Chaque commit représente un état du projet à un instant donné. On peut naviguer dans cet historique pour voir les modifications apportées au fil du temps :: ~/git-playground/alice-exercice-git (master) $ git switch --detach 033c477 HEAD is now at 033c477 create le corbeau et le renard ~/git-playground/alice-exercice-git (HEAD detached at 033c477) $ cat cr.txt Le corbeau et le renard Le fichier `cr.txt` est dans un état du passé, l'état dans lequel il était au moment du commit `033c477`. On revient au présent du projet :: ~/git-playground/alice-exercice-git (HEAD detached at 033c477) $ git switch master Previous HEAD position was 033c477 create le corbeau et le renard Switched to branch 'master' Your branch is up to date with 'origin/master'. Et le fichier ``cr.txt`` est de nouveau dans son état actuel :: ~/git-playground/alice-exercice-git (master) $ cat cr.txt Le corbeau et le renard Maitre Corbeau sur son arbre perché tenait en son bec un fromage. @@@@ Bob clone le repo central (7) ............................. C'est au tour de Bob d'apporter des modifications au projet qu'il a en commun avec Alice. Il clone lui aussi le repo central dans un répertoire dédié en spécifiant l'URL du repo distant (ici, le chemin local) :: ~/git-playground/alice-exercice-git (master) $ cd .. ~/git-playground $ git clone exercice-git.git bob-exercice-git Cloning into 'bob-exercice-git'... done. .. note:: Ici le rôle de Bob est joué également par l'élève : - l'élève endosse le rôle d'Alice lorsqu'il est dans le répertoire ``alice-exercice-git`` ; - et le rôle de Bob lorsqu'il est dans le répertoire ``bob-exercice-git``. Contrairement à Alice, lorsque Bob clone le repo central, il n'y a pas de message d'avertissement indiquant que le repo est vide, car il contient déjà les commit d'Alice. Maintenant le repo cloné de Bob est également disponible sous la forme d'un répertoire de travail :: ~/git-playground $ ls -la total 20 drwxrwxr-x 5 alice alice 4096 Jul 6 20:36 . drwxrwxr-x 7 alice alice 4096 Jul 6 20:13 .. drwxrwxr-x 3 alice alice 4096 Jul 6 20:18 alice-exercice-git drwxrwxr-x 3 alice alice 4096 Jul 6 20:36 bob-exercice-git drwxrwxr-x 7 alice alice 4096 Jul 6 20:34 exercice-git.git Pour la suite, Bob va travailler dans son propre répertoire de travail. On peut vérifier qu'il contient bien le fichier ``cr.txt`` créé puis modifié par Alice :: ~/git-playground $ cd bob-exercice-git ~/git-playground/bob-exercice-git (master) $ ls -la total 16 drwxrwxr-x 3 alice alice 4096 Jul 6 20:36 . drwxrwxr-x 5 alice alice 4096 Jul 6 20:36 .. -rw-rw-r-- 1 alice alice 92 Jul 6 20:36 cr.txt drwxrwxr-x 8 alice alice 4096 Jul 6 20:36 .git .. image:: images/misc-02-git-fig-18.png :width: 50 % :align: center On peut également contrôler la validité du contenu du fichier. Il contient bien toutes les modifications apportées par Alice :: ~/git-playground/bob-exercice-git (master) $ cat cr.txt Le corbeau et le renard Maitre Corbeau sur son arbre perché tenait en son bec un fromage. On vérifie également que le repo local de Bob est synchronisé avec le repo central. Il contient les deux commits d'Alice, et l'historique est identique à celui du repo central :: ~/git-playground/bob-exercice-git (master) $ git log commit afa888bba48d30a74d18116fd7a7e34f7091f5a4 Author: alice Date: Sun Jul 6 20:34:23 2025 +0200 add cr verse 2 commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard Bob a donc récupéré le repo central (augmenté du travail d'Alice) et va pouvoir contribuer à son tour. @@@@ Bob configure son identité .......................... Avant de commencer à ajouter du contenu, comme Alice, Bob doit configurer son identité dans le repo local. Cela permet d'associer ses commits à son nom et son adresse e-mail. On obtient les paramètres de configuration locale avec la commande :: ~/git-playground/bob-exercice-git (master) $ git config --local --list core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true remote.origin.url=~/git-playground/exercice-git.git remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master Pour le moment aucun utilisateur n'est associé à ce repo. Comme Alice, Bob doit définir son nom et son adresse e-mail :: ~/git-playground/bob-exercice-git (master) $ git config user.name "bob" ~/git-playground/bob-exercice-git (master) $ git config user.email "bob@esiee.fr" On vérifie également que la configuration a bien été prise en compte :: ~/git-playground/bob-exercice-git (master) $ git config --local --list core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true remote.origin.url=~/git-playground/exercice-git.git remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master user.name=bob user.email=bob@esiee.fr @@@@ Bob modifie le contenu (8) .......................... Bob va maintenant ajouter du contenu dans son répertoire de travail, d'abord en modifiant le fichier ``cr.txt`` qu'il a récupéré du repo central. Pour le moment ``cr.txt`` est dans l'état suivant :: ~/git-playground/bob-exercice-git (master) $ cat cr.txt Le corbeau et le renard Maitre Corbeau sur son arbre perché tenait en son bec un fromage. Bob ajoute un autre vers :: ~/git-playground/bob-exercice-git (master) $ echo "Maitre Renard par l'odeur alléché" >> cr.txt ~/git-playground/bob-exercice-git (master) $ cat cr.txt Le corbeau et le renard Maitre Corbeau sur son arbre perché tenait en son bec un fromage. Maitre Renard par l'odeur alléché Le fichier a été modifié dans le répertoire de Bob, mais la modification n'a pas été inscrite dans le repo local. On peut vérifier l'état du repo :: ~/git-playground/bob-exercice-git (master) $ git status -s M cr.txt et plus précisément, les différences entre la version locale et celle inscrite dans le repo:: ~/git-playground/bob-exercice-git (master) $ git diff diff --git a/cr.txt b/cr.txt index 8bd1c83..ff6cf27 100644 --- a/cr.txt +++ b/cr.txt @@ -2,3 +2,4 @@ Le corbeau et le renard Maitre Corbeau sur son arbre perché tenait en son bec un fromage. +Maitre Renard par l'odeur alléché .. note:: Ces opérations partagent une même logique, c'est à dire des modifications d'un même fichier. Plus généralement une logique regroupe des caractéristiques communes à des ajouts, des modifications ou des suppressions de fichiers, ou d'un ensemble de fichiers. On peut par exemple regrouper en un seul commit, les modifications de fichiers correspondant à une fonctionnalité. La granularité des commit est un choix de l'utilisateur qui doit être fait dans le sens de la construction d'un historique facile à exploiter. Bob fait le choix d'effectuer un commit après sa modification :: ~/git-playground/bob-exercice-git (master) $ git add . ~/git-playground/bob-exercice-git (master) $ git commit -m "add cr verse 3" [master 9391bb0] add cr verse 3 1 file changed, 1 insertion(+) On vérifie que l'historique contient maintenant la contribution de Bob :: ~/git-playground/bob-exercice-git (master) $ git log commit 9391bb01aa60740e10a2abc63a9b5279d9d90f0f Author: bob Date: Sun Jul 6 20:43:53 2025 +0200 add cr verse 3 commit afa888bba48d30a74d18116fd7a7e34f7091f5a4 Author: alice Date: Sun Jul 6 20:34:23 2025 +0200 add cr verse 2 commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard .. image:: images/misc-02-git-fig-19.png :width: 50 % :align: center @@@@ Bob crée un autre contenu (9) et (10) ..................................... Bob décide également d'ajouter une fable au répertoire. Il crée un fichier texte ``lt.txt`` et y écrit le contenu de la fable correspondante :: ~/git-playground/bob-exercice-git (master) $ echo "Le lièvre et la tortue" >> lt.txt ~/git-playground/bob-exercice-git (master) $ echo "" >> lt.txt ~/git-playground/bob-exercice-git (master) $ echo "Rien ne sert de courir ; il faut partir à point." >> lt.txt ~/git-playground/bob-exercice-git (master) $ echo "Le Lièvre et la Tortue en sont un témoignage." >> lt.txt On vérifie que le fichier a bien été créé dans le répertoire de travail de Bob :: ~/git-playground/bob-exercice-git (master) $ cat lt.txt Le lièvre et la tortue Rien ne sert de courir ; il faut partir à point. Le Lièvre et la Tortue en sont un témoignage. Le repo reflète l'état du répertoire de travail :: ~/git-playground/bob-exercice-git (master) $ git status -s ?? lt.txt Il est temps pour Bob d'ajouter ces fichiers au repo local :: ~/git-playground/bob-exercice-git (master) $ git add . ~/git-playground/bob-exercice-git (master) $ git commit -m "nouvelle fable : le lievre et la tortue" [master 86fd9c0] nouvelle fable : le lievre et la tortue 1 file changed, 4 insertions(+) create mode 100644 lt.txt On vérifie que l'historique local contient maintenant la nouvelle contribution de Bob :: ~/git-playground/bob-exercice-git (master) $ git log commit 86fd9c0da518f7461512bc5b4b543e4e04e6c4bb (HEAD -> master, origin/master, origin/HEAD) Author: bob Date: Sun Jul 6 20:48:23 2025 +0200 nouvelle fable : le lievre et la tortue commit 9391bb01aa60740e10a2abc63a9b5279d9d90f0f Author: bob Date: Sun Jul 6 20:43:53 2025 +0200 add cr verse 3 commit afa888bba48d30a74d18116fd7a7e34f7091f5a4 Author: alice Date: Sun Jul 6 20:34:23 2025 +0200 add cr verse 2 commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard L'indication ``HEAD -> master`` indique que la branche ``master`` de son repo local pointe sur le commit ``86fd9c0``. Ici le repo local de Bob est en avance sur le repo central qui ne contient que les contributions d'Alice :: ~/git-playground/bob-exercice-git (master) $ git --git-dir=../exercice-git.git log commit afa888bba48d30a74d18116fd7a7e34f7091f5a4 Author: alice Date: Sun Jul 6 20:34:23 2025 +0200 add cr verse 2 commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard Bob pousse ses modifications vers le repo central:: ~/git-playground/bob-exercice-git (master) $ git push To ~/git-playground/exercice-git.git afa888b..86fd9c0 master -> master et maintenant le repo central est à jour avec les contributions de Bob :: ~/git-playground/bob-exercice-git (master) $ git --git-dir=../exercice-git.git log commit 86fd9c0da518f7461512bc5b4b543e4e04e6c4bb Author: bob Date: Sun Jul 6 20:48:23 2025 +0200 nouvelle fable : le lievre et la tortue commit 9391bb01aa60740e10a2abc63a9b5279d9d90f0f Author: bob Date: Sun Jul 6 20:43:53 2025 +0200 add cr verse 3 commit afa888bba48d30a74d18116fd7a7e34f7091f5a4 Author: alice Date: Sun Jul 6 20:34:23 2025 +0200 add cr verse 2 commit c75293083f19c74a2cf1511e7ec0a3e89e43e45c Author: alice Date: Sun Jul 6 20:29:23 2025 +0200 add cr verse 1 commit 033c4775de53968803942fa96acd495839a3c811 Author: alice Date: Sun Jul 6 20:22:53 2025 +0200 create le corbeau et le renard .. image:: images/misc-02-git-fig-20.png :width: 50 % :align: center .. les interactions ci dessus sont réalisées par : $ python simulate.py --source git-playground --log git-playground.log --time 30 /!\ à chaque nouvelle exécution, les identifiants des commits changent @@@@ Création d'un conflit ..................... Jusqu'à présent, Alice et Bob ont travaillé de manière séquentielle, c'est à dire ne se sont jamais trouvé en situation de posséder dans son répertoire local, un même fichier, mais dans un état différent. Cette situation est bien sûr à privilégier, par une organisation rigoureuse du travail collaboratif et une bonne communication entre les membres de l'équipe. Cependant, il peut arriver que deux personnes modifient le même fichier en même temps, ce qui peut entraîner des conflits lors de la synchronisation des repos. .. note:: Ici la base de temps est fixée par la mise à jour du repo central. C'est uniquement lors de cet évènement périodique qu'un conflit peut être détecté. De manière symétrique, Alice doit maintenant récupérer les modifications apportées par Bob dans le repo central. Pour le moment son repo est dans l'état suivant :: git-playground/alice-exercice-git (master) $ git log --pretty=full commit 0c41c60cb5052a9e026e96950f727307a2d07909 (HEAD -> master, origin/master) Author: alice Commit: alice le corbeau et le renard (1) Puisqu'elle a déjà cloné le repo central (à ne faire qu'une seule fois), elle utilise maintenant la commande `git pull` pour synchroniser son repo local avec le repo central. Cette commande récupère les commits du repo distant et les fusionne avec la branche courante de son repo local :: git-playground/alice-exercice-git (master) $ git pull remote: Enumerating objects: 7, done. remote: Counting objects: 100% (7/7), done. remote: Compressing objects: 100% (6/6), done. remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (6/6), 1.34 KiB | 3.00 KiB/s, done. From //files/user/git-playground/exercice-git 0c41c60..08732e7 master -> origin/master Updating 0c41c60..08732e7 Fast-forward cr.txt | 9 --------- corbeau-renard.txt | 3 +++ lievre-tortue.txt | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) delete mode 100644 cr.txt create mode 100644 corbeau-renard.txt create mode 100644 lievre-tortue.txt Toutes les opérations de fusion sont effectuées automatiquement par Git. Il n'y a pas de conflit, car Alice n'a pas modifié les fichiers que Bob a ajoutés. .. warning:: Une organisation courante pour le travail collaboratif est de structurer le projet en 4 branches distinctes : - ``main`` : la branche principale qui contient la version stable du projet ; - ``alice`` : la branche de développement d'Alice ; - ``bob`` : la branche de développement de Bob ; - ``dev`` : la branche de développement contient les fonctionnalités en cours de développement. On crée une branche avec la commande ``git branch`` et on bascule dessus avec ``git switch``. Par exemple :: $ git branch alice $ git switch alice Ressources Git -------------- Git est un système de développement logiciel et de versioning puissant, mais sa maitrise avancée nécessite du temps d'apprentissage et de l'expérience. Ci dessous quelques ressources supplémentaires pour approfondir les choses : - `GIT Workflow - Georgia Tech - Software Development Process `_ - `Introduction à Git (IUT Lyon 1) `_ - `Gérez vos codes source avec Git (Open Classroom) `_ - `git - petit guide `_ - `Visualizing Git Concepts with D3 `_ - `A Visual Git Reference `_