0% ont trouvé ce document utile (0 vote)
29 vues70 pages

TP Git

Ce document est un guide détaillé sur l'utilisation de Git, couvrant des sujets tels que l'initialisation, la gestion des versions, le fonctionnement des versions, les branches et les dépôts distants. Il inclut également des quiz pour tester les connaissances acquises. Le document est destiné aux étudiants en informatique de l'Université de Poitiers.

Transféré par

vmaikoo08
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
29 vues70 pages

TP Git

Ce document est un guide détaillé sur l'utilisation de Git, couvrant des sujets tels que l'initialisation, la gestion des versions, le fonctionnement des versions, les branches et les dépôts distants. Il inclut également des quiz pour tester les connaissances acquises. Le document est destiné aux étudiants en informatique de l'Université de Poitiers.

Transféré par

vmaikoo08
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

TABLE DES MATIÈRES TABLE DES MATIÈRES

TP GIT Dépt Informatique - 26 avril 2021


G. Subrenat UFR SFA - Université de Poitiers

Git

Table des matières


1 Résumé et cadre de travail 4

2 Principe de Git 4
2.1 Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Quiz : Principe de Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

3 Initialisation de Git 5
3.1 Création d’un dépôt local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 Importation d’un dépôt distant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.3 Configuration du dépôt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3.1 Identité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3.2 Éditeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3.3 Couleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3.4 Gestion de l’authentification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.4 .gitkeep et .gitignore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.4.1 .gitkeep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.4.2 .gitignore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.5 Pour aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.6 Quiz : Initialisation de Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

4 Gestion des versions 10


4.1 Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.2 Exemple pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.2.1 Ajout du fichier .gitignore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.2.2 Ajout du fichier hello.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.2.3 Suite du module hello.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.3 Navigation dans les versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.3.1 Afficher l’historique : git log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.3.2 La numérotation des versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.3.3 Naviguer dans les versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.4 Quiz : Gestion des versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

5 Fonctionnement détaillé des versions 20


5.1 Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.2 Chaı̂nage des commit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.3 Nom de branche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

G. Subrenat - 1/70
TABLE DES MATIÈRES TABLE DES MATIÈRES

5.4 Pointeur HEAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22


5.4.1 Principe de fonctionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.4.2 Commit à partir d’une ancienne version : danger . . . . . . . . . . . . . . . . . . . 22
5.4.3 Revenir à la dernière version : mauvaise solution . . . . . . . . . . . . . . . . . . . 23
5.4.4 Revenir à la dernière version : bonne solution . . . . . . . . . . . . . . . . . . . . . 24
5.5 Quiz : Fonctionnement détaillé des versions . . . . . . . . . . . . . . . . . . . . . . . . . . 25

6 Branches 26
6.1 Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.2 Création d’une branche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.2.1 Point de départ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.2.2 Création . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.2.3 Changer la branche courante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.2.4 Nouveau commit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
6.2.5 Deuxième commit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
6.2.6 Retour sur la branche master . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
6.2.7 Un commit sur la branche master . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
6.3 Quelques commandes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
6.3.1 Commandes de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
6.3.2 Commandes risquées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
6.4 Fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
6.4.1 Fusion sans conflit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
6.4.2 Fusion sans conflit : fast forward . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
6.4.3 Fusion avec conflit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.4.4 Quelques commandes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.5 J’ai une urgence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
6.6 Quiz : Branches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

7 Repositories distants 40
7.1 Créer et paramétrer un compte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.1.1 Création . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.1.2 Générer les clés SSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.1.3 Enregistrer la clé SSH dans gitlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.2 Création et initialisation d’un projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.2.1 Repository distant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.2.2 Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
7.3 Cloner un dépôt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.3.1 Clonage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.3.2 Configuration et fonctionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.3.3 Quelques commandes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.4 Principe de fonctionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

G. Subrenat - 04/2021 - 2/70 Dépt Informatique - Université de Poitiers


TABLE DES MATIÈRES TABLE DES MATIÈRES

7.5 Les branches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45


7.5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.5.2 Quelques commandes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.6 Quelques exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
7.6.1 Tout se passe bien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
7.6.2 Deux push simultanés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
7.6.3 Récupérer les changements d’une branche . . . . . . . . . . . . . . . . . . . . . . . 52
7.6.4 Suppression définitive d’une branche . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.6.5 Création d’une nouvelle branche . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.7 Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.8 Quiz : Repositories distants : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

8 Conclusion 61

9 Réponses aux quiz 62


9.1 Réponses quiz : Principe de Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
9.2 Réponses quiz : Initialisation de Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
9.3 Réponses quiz : Gestion des versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
9.4 Réponses quiz : Fonctionnement détaillé des versions . . . . . . . . . . . . . . . . . . . . . 65
9.5 Réponses quiz : Branches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
9.6 Réponses quiz : Repositories distants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

G. Subrenat - 04/2021 - 3/70 Dépt Informatique - Université de Poitiers


2 PRINCIPE DE GIT

1 Résumé et cadre de travail


Le but de ce TP est d’appréhender le logiciel Git pour une utilisation de base :
- principe du logiciel
- versionnement
- branches
- fusion de branches
- conflits
- divers
Dans ce document l’apprentissage de Git se fera par l’exemple.
Il existe des interfaces graphiques pour manipuler Git, par exemple GitKraken ou Tortoise Git. De même
la plupart des IDE intègrent la gestion de Git.
C’est bien plus confortable et il faut les utiliser.
Mais dans ce TP nous utiliserons la ligne de commandes pour maı̂triser toutes les étapes de Git.
Les commandes seront données pour un système Linux, mais elles seront quasiment identiques 1 pour les
consoles de commandes des autres systèmes.

2 Principe de Git

2.1 Présentation

Git est un outil de versionnement. Autrement dit il garde une sauvegarde de toutes les versions d’un
projet et permet de visualiser à volonté les anciennes versions.
Il permet de travailler à plusieurs sur un projet et aide à gérer les conflits si plusieurs développeurs
modifient les mêmes fichiers.
Attention Git n’est pas un outil de gestion de projet, c’est uniquement un outil d’aide. En aucun il ne
remplace un chef de projet et une gestion rigoureuse.
Git utilise des branches. Cela permet de développer des versions “parallèles” du code (pour développer
et tester une fonctionnalité, pour explorer une solution, ...). Ensuite, si nécessaire, une nouvelle branche
est fusionnée avec la branche “principale”.
Git manipule des repositories (dépôts en français) distants ainsi qu’un repository local, ce qui sera étudié
plus tard dans le document.
Git peut tout à fait être utilisé pour un projet géré par un seul développeur, et c’est même recommandé.
Dans ce cas c’est la partie versionnement qui est utilisée (avec des branches si nécessaire).
Chaque version du projet concerne une seule fonctionnalité/action même si elle est minime. Il est fréquent
qu’un développeur crée plus de dix versions par jour.
On ne fait pas une version pour faire une sauvegarde ; chaque version doit être un code correct (dans la
mesure du possible).

2.2 Quiz : Principe de Git

Réponses page 62.


Question 1
plusieurs réponses possibles
Quel est le rôle de Git ?
- garder un historique de toutes les versions d’un projet
- travailler à plusieurs sur un projet
- faire de la gestion de projet
1. Voire complètement identiques

G. Subrenat - 04/2021 - 4/70 Dépt Informatique - Université de Poitiers


3 INITIALISATION DE GIT

Question 2
une seule réponse possible
Il est intéressant d’utiliser Git pour un projet avec un seul développeur.
- vrai
- faux
Question 3
une seule réponse possible
À quelle fréquence crée-t-on des versions ?
- très rarement : un logiciel a très peu de versions dans son existence
- chaque fois qu’un fichier source est définitivement terminé
- une fois par jour pour faire une sauvegarde
- toutes les heures pour ne pas perdre plus d’une heure de travail en cas de panne
- très souvent, chaque fois qu’une fonctionnalité est implémentée et testée
Question 4
une seule réponse possible
Git est très peu utilisé.
- vrai
- faux
Question 5
une seule réponse possible
Il existe des logiciels comparables à Git.
- vrai
- faux

3 Initialisation de Git

3.1 Création d’un dépôt local

Hypothèses :
- Nous nous plaçons dans le cas où un seul utilisateur utilise Git et que la gestion est locale à la
machine de l’utilisateur (le dépôt est local et il n’y a pas de dépôt distant).
- Nous partons d’un projet vide.
La première étape est de créer un répertoire et de se placer dedans 2 .
 
$ mkdir PROJET_C
$ cd PROJET_C
$ pwd
/home/gilles/TP/PROJET_C
$ ls -lA
total 0
 
On peut alors créer le dépôt :
 
$ git init
Dép^
ot Git vide initialisé dans /home/gilles/TP/PROJET_C/.git/
$ ls -lA
drwxrwxr-x 7 gilles gilles 4096 oct. 24 20:48 .git
 
On note la création du répertoire .git qui contient toute la configuration du dépôt. Il contiendra aussi
tout l’historique du projet.
Il ne faut pas modifier directement ce répertoire sinon on risque des destructions de données et/ou des
dysfonctionnements graves. Toute action doit passer les commandes git.
2. histoire de commencer en douceur

G. Subrenat - 04/2021 - 5/70 Dépt Informatique - Université de Poitiers


3.2 Importation d’un dépôt distant 3 INITIALISATION DE GIT

Remarque : si l’on veut travailler sur un projet existant et hébergé sur une machine distante, il faut le
rapatrier sur la machine locale avec la commande “git clone”. Ensuite le fonctionnement que nous allons
décrire sera le même.
Note : pour avoir une aide sur une commande git, la syntaxe est la suivante :
 
$ git help <cmd>
 

Par exemple 3 :
 
$ git help help
 

ou encore 4 :
 
$ git help init
 
Ça y est, le dépôt est prêt, enfin presque.

3.2 Importation d’un dépôt distant

Hypothèses :
- Nous voulons intégrer un projet, géré par Git, qui est présent sur internet (repository distant).
- Nous partons donc d’un projet en cours de développement.
La première étape est d’importer le repository distant en local. Prenons comme exemple un projet de
test de gitlab 5 :
 
$ git clone git@[Link]:gitlab-org/[Link]
Clonage dans ’gitlab-test’...
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights


and the repository exists.
 

Il faut avoir un compte paramétré sur gitlab pour rapatrier le projet 6 .


Si c’est c’est le cas, voici le résultat :
 
$ git clone git@[Link]:gitlab-org/[Link]
Clonage dans ’gitlab-test’...
remote: Enumerating objects: 72, done.
remote: Counting objects: 100% (72/72), done.
remote: Compressing objects: 100% (53/53), done.
remote: Total 1243 (delta 23), reused 27 (delta 5), pack-reused 1171
Réception d’objets: 100% (1243/1243), 10.72 MiB | 1.35 MiB/s, fait.
Résolution des deltas: 100% (563/563), fait.
Vérification de la connectivité... fait.
 
Note : lors d’une première connexion à gitlab, il peut y avoir un message d’avertissement :
 
The authenticity of host ’[Link] ([Link])’ can’t be established.
ECDSA key fingerprint is SHA256:LeK7q1yGdMDmcUfsNoHXPXv8Bw2b8efYRidmSRmGbCh.
Are you sure you want to continue connecting (yes/no)?
 
C’est normal. Il suffit de répondre par l’affirmative.
On peut alors descendre dans le répertoire fraı̂chement créé :
 
$ ls -l
drwxr-xr-x 12 gilles gilles 4096 2020-10-26 16:05 gitlab-test/
$ cd gitlab-test
$ pwd

3. l’équivalent du “man man” d’Unix


4. les commandes “git init --help” et “man git init” sont équivalentes
5. https ://[Link]/gitlab-org/gitlab-test
6. Pour être plus exact, il suffit d’avoir une clé SSH déposée sur un compte actif de gitlab.

G. Subrenat - 04/2021 - 6/70 Dépt Informatique - Université de Poitiers


3.3 Configuration du dépôt 3 INITIALISATION DE GIT

/home/gilles/TP/gitlab-test
$ ls -lA
drwxr-xr-x 8 gilles gilles 4096 2020-10-26 16:05 .git/
-rw-r--r-- 1 gilles gilles 100 2020-10-26 16:05 .gitattributes
-rw-r--r-- 1 gilles gilles 241 2020-10-26 16:05 .gitignore
-rw-r--r-- 1 gilles gilles 270 2020-10-26 16:05 .gitmodules
-rw-r--r-- 1 gilles gilles 22846 2020-10-26 16:05 CHANGELOG
...
drwxr-xr-x 2 gilles gilles 4096 2020-10-26 16:05 with space/
 
Pour envoyer des modifications sur le repository de gitlab il faut avoir des droits supplémentaires.
Que l’on ait créé un dépôt local ou importé un dépôt distant, le reste de la section s’applique in-
différemment.
La seule différence aura lieu lorsque des modifications seront apportées au projet : il y aura une commande
supplémentaire pour transmettre les changements au dépôt distant et ainsi les partager avec les autres
développeurs.
Reprenons les explications en se basant sur le dépôt local créé à la section précédente.

3.3 Configuration du dépôt

3.3.1 Identité

Lorsqu’une nouvelle version est créée 7 , elle est associée au développeur qui l’a faite afin que les autres
développeurs aient connaissance de l’auteur de chaque modification ; Git a donc besoin de connaı̂tre le
propriétaire du dépôt local 8 (nom et adresse mail).
Pour le montrer, lançons la commande suivante (qui sert à créer une nouvelle version 9 et que nous
détaillerons plus tard) :
 
$ git commit
*** Please tell me who you are.
Run
git config --global [Link] "you@[Link]"
git config --global [Link] "Your Name"
to set your account’s default identity.
Omit --global to set the identity only in this repository.
 
Il faut lancer les deux commandes proposées. Utiliser l’option --global indique que cette configuration
s’appliquera aux autres projets Git du compte utilisateur courant. Partons de l’hypothèse que nous
voulons une configuration locale au projet en cours :
 
$ git config [Link] "gilles@[Link]"
$ git config [Link] "Gilles"
 
Et maintenant :
 
$ git commit
Sur la branche master Validation initiale rien àvalider
 
Il n’y a plus d’erreur (et accessoirement Git nous indique qu’il n’est pas possible de créer une nouvelle
version puisqu’il n’y a eu aucune modification).

3.3.2 Éditeur

Chaque fois que l’on crée une nouvelle version, il faut saisir un message explicatif dans un éditeur de
texte. L’éditeur choisi par défaut par Git pourrait ne pas convenir ; il est possible d’en choisir un autre.
Première solution avec la variable d’environnement GIT EDITOR (à mettre dans le .bashrc) :
7. on parle de commit
8. Si le projet a été importé via un git clone, on parle malgré tout d’un dépôt local : le répertoire courant n’est qu’une
copie du dépôt distant, et donc est bien local. Il y aura une commande spéciale (git push) pour transmettre les modifications
locales vers le dépôt distant.
9. Notons que cela n’a pas de sens puisque nous n’avons encore rien rajouté dans le projet.

G. Subrenat - 04/2021 - 7/70 Dépt Informatique - Université de Poitiers


3.4 .gitkeep et .gitignore 3 INITIALISATION DE GIT

 
$ export GIT_EDITOR=[Link]
 
Seconde solution (que nous choisissons) avec le fichier de configuration de Git :
 
$ git config [Link] gedit
 
L’option --global est possible.
La première solution est prioritaire sur la seconde. Le fichier de configuration local est prioritaire sur le
fichier de configuration global.

3.3.3 Couleur

Pour activer la couleur dans les affichages de Git, le paramètre est [Link] qui peut prendre les valeurs
false, auto (valeur par défaut), true et always. Par exemple :
 
$ git config [Link] true
 

3.3.4 Gestion de l’authentification

(attention le contenu de cette sous-section est incertain, à vérifier avec d’autres sources)
Lorsqu’on se connecte à des dépôts distants, ceux-ci demandent généralement une phase d’authentification
qu’il faut potentiellement renseigner à chaque accès au dépôt. Il peut rapidement être pénible de devoir
saisir fréquemment ses identifiants.
Git intègre un dispositif de gestion des identifiants avec le paramètre [Link] (toujours avec la
possibilité de l’option --global).
Pour Windows :
 
$ git config [Link] wincred
 
Pour Linux :
 
$ git config [Link] cache
 
Pour Mac :
 
$ git config [Link] osxkeychain
 
Beaucoup de serveurs Git (dont gitlab) autorisent l’authentification par clés SSH, ce qui dispense des
phases d’authentification explicites.

3.4 .gitkeep et .gitignore

3.4.1 .gitkeep

Git ne gère que les fichiers mais pas les répertoires, autrement dit il ignorera les répertoires vides.
La seule solution pour traquer un répertoire vide est ... qu’il ne soit pas vide.
L’habitude est que l’on mette à l’intérieur un fichier vide nommé .gitkeep 10 .
Ce fichier peut être supprimé une fois que d’autres fichiers ont été ajoutés au répertoire.
Une autre solution est d’avoir un fichier vide nommé .gitignore avec le même effet. La différence est que
ce dernier fichier a une signification particulière pour Git (cf. ci-dessous).
10. N’importe quel autre nom de fichier aurait le même effet, ce n’est qu’une convention.

G. Subrenat - 04/2021 - 8/70 Dépt Informatique - Université de Poitiers


3.5 Pour aller plus loin 3 INITIALISATION DE GIT

3.4.2 .gitignore

Tous les fichiers n’ont pas vocation à être gérés par Git, i.e. n’ont pas être sauvegardés dans les dépôts.
Par exemple :
- les produits d’une compilation : fichiers objets, exécutables
- les fichiers de sauvegarde temporaires des éditeurs
- ...
Toutes les règles décrivant les fichiers ignorés doivent se trouver dans des fichiers nommés .gitignore. Il
peut y avoir des fichiers .gitignore dans plusieurs répertoires ; la portée des règles d’un tel fichier est son
répertoire ainsi que les sous-répertoires descendants.
Voici un exemple simple de fichier .gitignore :
 
# tous les fichiers objets
*.o

# les sauvegardes temporaires des éditeurs de texte


*~
*.bak
 
Voici un fichier .gitignore qui empêche tout le contenu du répertoire d’être géré par Git :
 
*
!.gitignore
 
On note la négation pour indiquer que le fichier .gitignore doit lui être géré par Git.
Nous n’irons, dans le cadre de ce document, pas plus loin dans les explications.

3.5 Pour aller plus loin

Les paramètres de configuration globale de Git se trouvent dans le fichier $HOME/.gitconfig


Les paramètres de configuration locale de Git se trouvent dans le fichier /.git/config
Rappel : il faut éviter d’éditer ces fichiers à la main, mais plutôt passer par la commande “git config”.
Voici quelques commandes de configuration :
git config --list : liste tous les paramètres
git config --local --list : liste tous les paramètres locaux
git config --global --list : liste tous les paramètres globaux
git config --unset <nom-param> : supprime un paramètre local
git config --global --unset <nom-param> : supprime un paramètre global
git config <nom-param> : affiche la valeur du paramètre utilisé (cf. ci-dessous)
git config --local <nom-param> : affiche la valeur du paramètre local
git config --global <nom-param> : affiche la valeur du paramètre global
Commande : git config <nom-param> :
- si le paramètre n’est défini qu’en local ou (exclusif) qu’en global, la commande affiche la valeur,
- si le paramètre est défini à la fois en local et en global, la commande affiche la version locale.

3.6 Quiz : Initialisation de Git

Réponses page 62.


Question 1
une seule réponse possible
Un projet géré par Git en local doit toujours être lié à un dépôt distant géré par un serveur.
- vrai
- faux
Question 2
plusieurs réponses possibles
Quelle(s) commande(s) permet(tent) d’enregistrer son nom dans Git ?

G. Subrenat - 04/2021 - 9/70 Dépt Informatique - Université de Poitiers


4 GESTION DES VERSIONS

- git config [Link] ”mon nom”


- git init [Link] ”mon nom”
- git config --global [Link] ”mon nom”
- git init --global [Link] ”mon nom”
- git --global config [Link] ”mon nom”
- git --global init [Link] ”mon nom”
- export GIT AUTHOR NAME=”mon nom”
Question 3
une seule réponse possible
Je ne renseigne pas mon nom et mon email dans la configuration de Git.
- vrai : si je fais une bêtise, les autres développeurs ne pourront pas me retrouver
- faux : ainsi les autres développeurs sauront sur quelles parties je suis intervenu
Question 4
plusieurs réponses possibles
Je veux enregistrer un répertoire vide dans Git. Je mets dans le répertoire le fichier suivant :
- .gitkeep vide
- .gitkeep avec un espace dedans
- .gitignore vide
- .empty vide
- .vide vide
Question 5
une seule réponse possible
Les fichiers .gitignore sont inutiles, autant sauvegarder un maximum d’informations dans les repositories
Git.
- vrai
- faux

4 Gestion des versions

4.1 Préambule

Nous somme dans l’hypothèse où il n’y a qu’une seule branche (généralement appelée master) dans
laquelle vont se succéder linéairement les différentes versions.
Nous nous plaçons dans la configuration suivante :
- Les données sont centralisées (cf. ci-dessous) dans un repository distant (par exemple hébergé par
gitlab) qui sert de référence.
- Nous avons une copie dans le repository local (obtenu par “git clone”).
- Nous sommes le seul développeur actif. Autrement dit le repository distant n’est pas modifié pendant
que nous travaillons en local. Ainsi nous ne gérons pas, dans un premier temps, les conflits 11 avec
les autres développeurs.
Nous parlons de repository central, mais Git est un outil décentralisé. Ceci dit pour simplifier les expli-
cations nous supposons que :
- Il y a un repository central et distant qui sert de référence.
- Chaque développeur travaille dans son repository local et se synchronise uniquement avec le repo-
sitory central.
Avertissement : pour l’instant nous avons uniquement un repository local (obtenu par “git init”) et
nous ne pourrons pas faire les instructions manipulant le repository distant. Elles seront tout de même
indiquées pour information.
La démarche pour créer une nouvelle version est la suivante :
11. au sens Git du terme

G. Subrenat - 04/2021 - 10/70 Dépt Informatique - Université de Poitiers


4.2 Exemple pratique 4 GESTION DES VERSIONS

- On ajoute et on modifie les fichiers nécessaires.


- On vérifie que le code est correct.
- On indique à Git quels fichiers font partie de la future nouvelle version (tous les fichiers créés ou
modifiés ne sont pas obligatoirement à prendre en compte).
- On crée la nouvelle version sur le repository local (commit).
- Si on utilise un repository distant, on lui envoie la nouvelle version (push).
Note : il est possible de faire plusieurs versions locales d’affilée pour les envoyer en une seule fois au
repository distant (par exemple si on n’a pas accès à internet).
Plus en détails cela donne :
- Rappel : une version correspond à une seule fonctionnalité même si elle est minime.
- Rappel : une version correspond à un code correct.
- On vérifie qu’une fonctionnalité n’est pas en cours de développement 12 (cf. rappel ci-dessus) :
 
$ git status
 
- On part d’un état “propre”, c’est à dire que l’on rapatrie la dernière version en provenance du
repository central 13 14 :
 
$ git pull
 
- On applique autant de fois que nécessaire les opérations suivantes :
- création/modification de fichiers avec son IDE favori
- tests et débuggage
- On vérifie les fichiers potentiellement concernés par la nouvelle version :
 
$ git status
 
- On indique à Git quels fichiers doivent réellement faire partie de la nouvelle version :
 
$ git add <liste fichiers>
 
ou plus simplement si tous les fichiers sont concernés :
 
$ git add .
 
- On crée la nouvelle version sur le repository local :
 
$ git commit
 
- On envoie la nouvelle version sur le repository distant :
 
$ git push
 

4.2 Exemple pratique

Rappel il n’y a pas de repository distant, donc les affichages des commandes Git seront plus courts qu’avec
un projet partagé.

4.2.1 Ajout du fichier .gitignore

Le dépôt est complètement vide, mais il faut prendre tout de suite les bonnes habitudes et on vérifie que
l’état du dépôt est “propre”.
 
$ git status
Sur la branche master

Validation initiale

rien à valider (créez/copiez des fichiers et utilisez "git add" pour les suivre)
 
12. Même si un développeur doit savoir s’il a un développement en cours.
13. cf. explication ci-dessus sur la notion de central et décentralisé
14. Avec nos hypothèses, comme nous sommes le seul développeur, nous devons avoir de fait la dernière version en local.

G. Subrenat - 04/2021 - 11/70 Dépt Informatique - Université de Poitiers


4.2 Exemple pratique 4 GESTION DES VERSIONS

Il faut théoriquement vérifier que l’on a la dernière version :


 
$ git pull
fatal: Aucun dép^
ot distant spécifié. Veuillez spécifier une URL ou un nom
distant depuis lesquels les nouvelles révisions devraient ^ etre récupérées.
 
Et on obtient bien un message d’erreur adéquat.
On crée le fichier .gitignore :
 
$ gedit .gitignore
$ ls -lA
drwxrwxr-x 7 gilles gilles 4096 2020-10-27 17:34 .git/
-rw-rw-r-- 1 gilles gilles 31 2020-10-27 17:35 .gitignore
$ cat .gitignore
# tous les fichiers objets
*.o
 
Voyons l’état du repository local :

Nous nous précipitons 15 alors pour enregistrer notre première version :

En effet, il faut d’abord indiquer à Git l’ensemble des fichiers, parmi ceux qu’il propose, qu’il doit intégrer
à la nouvelle version. En l’occurrence, comme on les veut tous (il n’y en a qu’un !), on indique la commande
globale :
 
$ git add .
 
Mais la nouvelle version n’est toujours pas créée, voyons ce qu’il dit de l’état du repository :

Le fichier .gitignore est maintenant indexé et nous pouvons enregistrer, en local, la nouvelle version :
 
$ git commit
[master (commit racine) b1bea7d] Création du fichier .gitignore : non prise en compte des .o
1 file changed, 2 insertions(+)
create mode 100644 .gitignore
 
15. et bien entendu ... il ne faut pas confondre vitesse et précipitation !

G. Subrenat - 04/2021 - 12/70 Dépt Informatique - Université de Poitiers


4.2 Exemple pratique 4 GESTION DES VERSIONS

Git a lancé l’éditeur choisi lors de la configuration (gedit dans le cas présent) pour écrire un message
expliquant la nouvelle version. Il est indispensable de saisir un message le plus clair et complet possible,
et il ne faut pas hésiter à mettre plusieurs lignes.
Git interdit les messages vides, et des messages du style “ ” ou “modif” sont à proscrire.
Voici ce qu’a proposé l’éditeur de texte. Seule la première ligne a été saisie :

 affichage éditeur de texte



1 Création du fichier .gitignore : non prise en compte des .o
2 # Veuillez saisir le message de validation pour vos modifications. Les lignes
3 # commençant par ’#’ seront ignorées, et un message vide abandonne la validation.
4 # Sur la branche master
5 #
6 # Validation initiale
7 #
8 # Modifications qui seront validées :
9 # nouveau fichier : .gitignore
10 #
 
Notons également le numéro associé à ce commit : b1bea7d.
Normalement le repository local est maintenant dans un état propre :
 
$ git status
Sur la branche master
rien à valider, la copie de travail est propre
 
Il faut théoriquement envoyer notre version sur le repository distant pour que les autres développeurs y
aient accès :

Et on obtient bien un message d’erreur adéquat puisque nous n’avons pas de repository distant.
Pour la suite, tant que nous n’utiliserons pas de repository distant, nous passerons sous silence les phases
de pull et de push.

4.2.2 Ajout du fichier hello.c

Il faut s’assurer que le repository local est propre et qu’on a bien rapatrié la dernière version si on utilise
un repository distant (cf. section précédente).
Nous allons programmer un “hello world !” et le tester avant d’en faire une nouvelle version.
Rappelez-vous qu’on crée une nouvelle version avec un code correct et testé.
Voici ce que peut donner une session de travail :

Une fois la fonctionnalité terminée et testée 16 , il faut créer une nouvelle version. Mais avant cela, il faut
16. manifestement ce n’était pas inutile

G. Subrenat - 04/2021 - 13/70 Dépt Informatique - Université de Poitiers


4.2 Exemple pratique 4 GESTION DES VERSIONS

toujours vérifier l’état du repository local :

Si on avait créé la nouvelle version sans vérification, l’exécutable y aurait été inclus. On s’aperçoit donc
que le fichier hello ne doit pas intégrer la nouvelle version. Pour cela trois possibilités :
- on le supprime avant le commit
- on le rajoute au .gitignore
- on fait un “git add” sur mesure.
Nous choisissons la troisième solution, suivie d’un commit :

Par la même occasion, nous voyons qu’il est possible d’intégrer directement un message court lors du
commit, sans passer par l’éditeur de texte.
Notons également le numéro associé à ce commit : d88c921.
Et lorsqu’il y aura un dépôt distant, il faudra penser au push.

4.2.3 Suite du module hello.c

Nous allons étoffer notre projet avec un module manip (couple manip.h et manip.c) et un Makefile.
Tout d’abord le codage et les tests :

Puis la vérification habituelle :

G. Subrenat - 04/2021 - 14/70 Dépt Informatique - Université de Poitiers


4.2 Exemple pratique 4 GESTION DES VERSIONS

Quelques remarques :
- On voit bien la différences entre les fichiers modifiés et les fichiers nouvellement créés.
- Les .o n’apparaissent pas dans l’état du repository : c’est grâce au .gitignore créé plus tôt.
Nous allons supprimer tous les fichiers inutiles :

et créer la nouvelle version :

Notons le numéro associé à ce commit : 59ea874.


Nous nous apercevons, trop tard, qu’il y a une faute d’orthographe dans le message associé à cette nouvelle
version.

G. Subrenat - 04/2021 - 15/70 Dépt Informatique - Université de Poitiers


4.3 Navigation dans les versions 4 GESTION DES VERSIONS

Il est possible de corriger un message à condition :


- de le faire avant d’autres modifications,
- et surtout avant d’avoir envoyé la version sur le repository distant.
Ce type de commande est dangereux et peut conduire à des incohérences dans le repository ; à éviter si
possible.
Voici la correction :

On note que le numéro associé au commit a changé 17 : ffcfa7e.

4.3 Navigation dans les versions

Nous arrivons dans une partie particulièrement puissante de Git : consulter l’historique et naviguer dans
les versions.

4.3.1 Afficher l’historique : git log

En premier lieu, rappelons que la commande suivante existe :


 
$ git help log
 
Le manuel fait près de 2000 lignes.
Voyons la commande de base :

Voici les informations affichées :


- Les versions s’affichent de la plus récente à la plus ancienne.
- Pour chaque version on a :
- son numéro
- son auteur
- sa date
- le message de description

L’option --oneline permet un affichage condensé :


17. Pour être exact le numéro du commit n’a pas changé mais un nouveau a été créé. Le commit 59ea874 existe toujours
mais n’est plus rattaché à la branche master : il est orphelin.

G. Subrenat - 04/2021 - 16/70 Dépt Informatique - Université de Poitiers


4.3 Navigation dans les versions 4 GESTION DES VERSIONS

Dans la suite du document, nous utiliserons fréquemment cette option afin de limiter la taille des captures
d’écran.
L’option --decorate permet d’afficher sur l’historique :
- le nom des branches (une seule pour l’instant pour nous : master)
- sur quelle version on travaille : HEAD (lorsqu’on saura se déplacer dans l’historique)

Nous allons rapidement voir que cette notion de nom de branche et de HEAD est primordiale : ne pas
parfaitement les comprendre peut conduire à des pertes de données (notion de commit orphelin).
L’option --branches avec sa compagne --graph permettent de visualiser :
- la totalité de la branche courante lorsqu’on se déplace dedans
- toutes (ou presque) les autres branches du projet.
Ce sera plus clair avec les exemples qui ne tarderont pas à venir. Dans l’état actuel, elles n’apportent pas
de nouvelles informations.

4.3.2 La numérotation des versions

Chaque version est référencé par un identifiant unique en hexadécimal de 40 chiffres.


Actuellement nous avons les trois versions suivantes :
- ffcfa7eaecac751613c0a4b4f14fed65404c2a87
- d88c921cb86e70174696d48072a222b3d492bffc
- b1bea7d83365b0862df980b7c60dae59366d38fc
On appelle ces identifiants des SHA-1 (prononcer “cha ouane”) car ils sont fabriqués par ... la fonction
de hashage SHA-1.
C’est en précisant un tel numéro que l’on peut se déplacer dans l’historique.
On voit tout de suite la pénibilité de manipuler des identifiants aussi longs et peu intuitifs.
Aussi Git permet de manipuler ces identifiants en utilisant uniquement les premiers chiffres (au mini-
mum 4, et généralement 7).
D’ailleurs lors des créations des versions (commit), les numéros n’étaient donnés qu’avec les 7 premiers
chiffres.
La commande “git log” précise tous les chiffres.
La commande “git log –oneline” ne précise que 7 chiffres.
En ne précisant que les premiers chiffres, on pourrait avoir des conflits mais la probabilité est faible
(268 millions de possibilités avec 7 chiffres). En cas de conflit, il suffira de préciser plus de chiffres.
Notons qu’il est possible d’apposer des tags sur certaines versions afin de les manipuler avec des noms
plus explicites.

4.3.3 Naviguer dans les versions

La commande est :
 
$ git checkout <sha-1>
 
Pour être précis, la commande “git checkout” permet aussi de naviguer dans les branches.
Par exemple nous allons revenir à la première version (celle où il n’y avait que le fichier .gitignore) qui a
pour numéro b1bea7d.

G. Subrenat - 04/2021 - 17/70 Dépt Informatique - Université de Poitiers


4.3 Navigation dans les versions 4 GESTION DES VERSIONS

Dans un premier temps, vérifions que nous sommes sur la version la plus récente :

Analyse :
- C’est la référence (on parle aussi de pointeur 18 ) HEAD qui indique sur quelle version nous sommes.
- Comment savoir que nous sommes sur la version la plus récente ? C’est la référence master qui nous
l’indique. La référence master pointe toujours (par définition) sur la version la plus récente. Comme
HEAD et master pointent sur la même version 19 , alors la version courante est bien la plus récente.
- Le listing du répertoire montre bien les derniers fichiers.
Changeons maintenant de version :

Analyse :
- Pour l’instant nous laissons de côté la notion de “detached HEAD” ou de création d’une nouvelle
branche. Disons juste que cela signifie qu’il ne faut pas faire des modifications et des commit, à
moins de créer une branche.
- La dernière ligne nous rappelle le message associé à la version que nous venons de restaurer.
Le contenu du répertoire est maintenant :

Nous avons bien l’état du code source au moment de la première version.


Attention tout de même :
- Tous les fichiers qui ne sont pas intégrés à des versions resteront présents au fur et à mesure de la
navigation
- Si des fichiers, déjà intégrés à la dernière version, sont en cours de modification, il ne sera pas
possible de naviguer dans l’historique 20 .
Que nous dit la commande “git log ?

Nous ne voyons que l’historique jusqu’à la version choisie, ce qui nous permet d’être dans les conditions
de l’époque. Ceci dit il est souvent préférable de situer la version courante dans l’ensemble des versions ;
une première utilité de l’option --branches (que nous associerons systématiquement à l’option --graph)
apparaı̂t alors.
18. Le terme de pointeur n’est pas un hasard comme nous le verrons dans une prochaine section.
19. Si on regarde attentivement, HEAD ne pointe pas au même endroit que master, mais HEAD pointe sur master ;
HEAD est donc ici un pointeur sur un pointeur. Cette distinction est importante comme nous le verrons par la suite.
20. cf. malgré tout, la commande : git stash

G. Subrenat - 04/2021 - 18/70 Dépt Informatique - Université de Poitiers


4.4 Quiz : Gestion des versions 4 GESTION DES VERSIONS

Nous voyons que notre version courante (marquée par HEAD) est remontée de deux positions dans le
temps par rapport à la version la plus récente de la branche courante 21 (marquée par master).
Après avoir regardé le code source de la version 1 de notre projet, il est temps de revenir à la version la
plus récente pour continuer à développer.
Il y a alors deux commandes possibles :
 
$ git checkout ffcfa7e # NON
 
ou
 
$ git checkout master # OUI
 

La première est à proscrire 22 . Pour revenir en haut d’une branche, on passe toujours le nom de la branche
à la commande checkout et jamais le SHA-1 (nous expliquerons en détail ces subtilités dans une prochaine
section) :

Nous pouvons désormais continuer à développer le code dans la branche principale.

4.4 Quiz : Gestion des versions

Réponses page 63.


Question 1
une seule réponse possible
Git est un gestionnaire centralisé avec un dépôt principal et des dépôts secondaires.
- vrai
- faux
Question 2
plusieurs réponses possibles
La commande “git status” ?
- elle affiche le copyright du logiciel Git
- elle indique les changements effectués depuis la dernière version enregistrée
- elle indique les fichiers qui seront intégrés à la nouvelle version et ceux qui ne le seront pas
- elle indique si le projet est public ou privé et les coordonnées du propriétaire
Question 3
plusieurs réponses possibles
Pourquoi la commande “git commit” crée une nouvelle version en local et ne la propage pas directement
sur le repository distant ?
- Il n’existe pas obligatoirement un repository distant.
- Le système étant décentralisé, c’est au développeur de choisir sur quels dépôts distants il désire
propager la nouvelle version.
- Le développeur peut ainsi annuler des commit, ce qui ne sera plus possible une fois la version
transmise.
- Le développeur n’a pas obligatoirement accès à internet.
Question 4
plusieurs réponses possibles
21. Rappelons que pour l’instant il n’y a qu’une seule branche, nommée par défaut master, dans notre projet.
22. sauf, comme toujours, si on sait ce que l’on fait

G. Subrenat - 04/2021 - 19/70 Dépt Informatique - Université de Poitiers


5 FONCTIONNEMENT DÉTAILLÉ DES VERSIONS

Pourquoi la commande “git add” est nécessaire et pourquoi tous les fichiers créés ou modifiés ne sont pas
directement intégrés à une nouvelle version ?
- Cela réduit le trafic réseau.
- Cela réduit la place occupée sur disque.
- Cela permet au développeur d’avoir une double validation avant de créer la version.
- Des informations inutiles perturberaient les autres développeurs et généreraient des versions inutiles.
Question 5
une seule réponse possible
Les SHA-1 pour identifier les versions sont trop risqués car il y a des risques de conflits (i.e. que deux
versions aient le même identifiant).
- vrai
- faux
Question 6
une seule réponse possible
On peut identifier une version par autre chose qu’un SHA-1.
- vrai
- faux
Question 7
plusieurs réponses possibles
La commande “git checkout” permet de :
- naviguer dans l’historique des versions d’une branche
- changer la branche active
- supprimer physiquement une version devenue inutile
- créer une nouvelle branche
Question 8
une seule réponse possible
On peut modifier une version ancienne et faire des commit ?
- vrai
- faux

5 Fonctionnement détaillé des versions

5.1 Préambule

L’identification des versions avec des SHA-1 est assez claire, mais il reste des zones d’ombre au sujet des
références que sont HEAD et master (et les noms des branches en général).
Les SHA-1 sont “physiquement” (i.e. indéfectiblement) liés à un commit 23 : il est impossible de changer
le SHA-1 d’un commit.
Un nom de branche (master pour l’instant) n’est qu’un pointeur sur un commit. Et comme tout pointeur
il est susceptible de se déplacer le long des commit.
Dans une utilisation normale 24 , ce pointeur se déplace automatiquement et désigne toujours le commit
le plus récent de la branche.
HEAD est un pointeur particulier :
- il se déplace à volonté
- il désigne la version de travail courante
- il peut pointer sur un SHA-1 (comme le fait un nom de branche)
- et plus perturbant (pour l’instant) il peut pointer sur un nom de branche (donc un pointeur sur un
pointeur)
23. commit ≡ version et de fait commit ≡ version ≡ SHA-1
24. qu’il est fortement conseillé de suivre

G. Subrenat - 04/2021 - 20/70 Dépt Informatique - Université de Poitiers


5.2 Chaı̂nage des commit 5 FONCTIONNEMENT DÉTAILLÉ DES VERSIONS

Vraisemblablement ce n’est pas clair, et nous allons expliciter chaque point dans la suite.

5.2 Chaı̂nage des commit

Sur une branche, les versions/commit sont reliés entre eux avec un chaı̂nage arrière simple : la version la
plus récente pointe sur l’avant-dernière qui elle-même pointe sur l’antépénultième et ainsi de suite jusqu’à
la première version du projet.
Une autre façon est de dire que les versions sont gérées comme une pile.
Quand nous gérerons plusieurs branches, nous verrons que les versions forment un arbre 25 chaı̂né “à
l’envers”, i.e. un fils pointe sur son père, et la racine de l’arbre est le premier commit.
Nous avons tout d’abord ajouté deux commit pour arriver à un total de 5 versions et rendre ainsi les
schémas plus clairs :

Et voici le chaı̂nage implémenté dans Git :


74d1180
d88c921

da57328
b1bea7d

ffcfa7e

La première version est à gauche et la plus récente à droite.

5.3 Nom de branche

Si l’on pointe sur la version la plus récente, alors grâce au chaı̂nage on peut revenir à n’importe quelle
version de la branche.
En revanche, si on pointe sur une version intermédiaire, il n’est plus possible de revenir à la version la
plus récente en se servant du chaı̂nage.
Une solution serait de connaı̂tre le SHA-1 de la version la plus récente. Mais :
- c’est particulièrement pénible à se souvenir
- et il change à chaque nouvelle version.
- si on l’oublie, le projet est perdu 26 .
Bref ce n’est pas la solution.
Aussi chaque branche a un pointeur dédié qui pointe en permanence sur le SHA-1 de la version la plus
récente. Ce pointeur a pour nom le nom de la branche 27 : dans notre cas c’est master.
D’une part il est plus facile de se souvenir du nom des branches, d’autre part il existe une commande (git
branch) qui donne la liste de toutes les branches.
Si on utilise correctement Git ce pointeur se déplace automatiquement chaque fois qu’une nouvelle version
est créée.
25. ou plus exactement un DAG
26. Ce n’est pas tout à fait vrai, il est possible d’obtenir la liste de tous SHA-1, y compris les orphelins.
27. En fait c’est le contraire : le nom de la branche est déterminé par le nom du pointeur.

G. Subrenat - 04/2021 - 21/70 Dépt Informatique - Université de Poitiers


5.4 Pointeur HEAD 5 FONCTIONNEMENT DÉTAILLÉ DES VERSIONS

Voici le schéma réactualisé :

74d1180
d88c921

da57328
b1bea7d

ffcfa7e
master

Détruire un branche revient juste à supprimer le pointeur et en aucun cas les données.
Cependant si on détruit la branche (et c’est assez facile à faire), on ne peut plus accéder aux versions (à
part des manipulations peu aisées, cf. commande “git fsck”). On parle alors de SHA-1 orphelins.

5.4 Pointeur HEAD

5.4.1 Principe de fonctionnement

Il reste à désigner la version courante de travail. Pour cela il y a un pointeur dédié nommé HEAD.
En règle général HEAD pointe sur la version la plus récente d’une branche, autrement dit au même
endroit que le pointeur de branche (master pour l’instant dans notre cas) ; tout simplement parce que
habituellement on travaille sur la dernière version d’un projet.
Mais nous avons vu, avec la commande “git checkout”, que HEAD pouvait pointer sur n’importe quel
autre commit plus ancien.
Nous allons commencer par expliciter ce dernier cas, même si ce n’est pas le plus fréquent. Supposons
que nous ayons tapé la commande :

On note à nouveau un message anxiogène avec cette notion ésotérique de “detached HEAD”.
Nous arrivons alors dans la configuration :
74d1180
d88c921

da57328
b1bea7d

ffcfa7e

HEAD master

Rappelons que tous les nouveaux fichiers et toutes les modifications faits après cette version n’apparaissent
plus dans les répertoires de travail.

5.4.2 Commit à partir d’une ancienne version : danger

A priori on ne peut pas faire de commit puisqu’il y a déjà une version après la version courante. Aussi
généralement, lorsqu’on se positionne sur une version passée, on se contente de consulter.

G. Subrenat - 04/2021 - 22/70 Dépt Informatique - Université de Poitiers


5.4 Pointeur HEAD 5 FONCTIONNEMENT DÉTAILLÉ DES VERSIONS

Voyons cependant ce qu’il se passerait si on apportait une modification suivie d’un commit : il y aurait
bien une nouvelle version qui n’écraserait pas la version ffcfa7e mais qui apparaı̂trait à côté avec son
propre SHA-1 (inventé pour l’occasion) :

74d1180
d88c921

da57328
b1bea7d

ffcfa7e
master

8c31f5a

HEAD

On voit que le pointeur HEAD s’est naturellement mis sur la nouvelle version. Mais le problème principal
apparaı̂t : lorsqu’on remettra le pointeur HEAD en bout de branche master, ce nouveau SHA-1 sera
inaccessible (à moins de noter le SHA-1 sur un document extérieur ce qui n’est pas raisonnable).
L’expression “detached HEAD” est un peu plus claire : tous les commit créés seront détachés, autrement
dit inaccessibles.
Lorsque nous aborderons les branches multiples, nous verrons qu’il est possible de rendre ces nouveaux
commit accessibles.
Revenons à la situation d’origine :
74d1180
d88c921

da57328
b1bea7d

ffcfa7e

HEAD master

5.4.3 Revenir à la dernière version : mauvaise solution

Il reste à revenir sur la dernière version de la branche master pour continuer à développer le projet. et il
y a deux possibilités.
Commençons par la mauvaise :

Pourtant aucun message ne nous alerte. En réalité nous étions déjà dans le mode “detached HEAD” et
nous le restons : Git ne nous met pas des messages alarmistes chaque fois.
Regardons de près la commande “git log” :

Et plus précisément la première ligne :

G. Subrenat - 04/2021 - 23/70 Dépt Informatique - Université de Poitiers


5.4 Pointeur HEAD 5 FONCTIONNEMENT DÉTAILLÉ DES VERSIONS

HEAD et master sont séparés par une virgule ce qui signifie qu’ils sont indépendants bien que pointant
sur le même commit. Nous sommes dans la configuration suivante :

74d1180
d88c921

da57328
b1bea7d

ffcfa7e
master HEAD

Si nous faisons un nouveau commit, nous arrivons sur la configuration (avec un SHA-1 inventé pour
l’occasion) :

74d1180
d88c921

da57328

184de39
b1bea7d

ffcfa7e

master HEAD

Un premier problème est que master ne pointe pas sur la dernière version de la branche ce qui est
incohérent avec un pointeur de branche.
Le deuxième problème (lié au premier) est que si on déplace HEAD sur une version passée, il n’y a plus
moyen de revenir sur la dernière version (à moins de noter ce SHA-1 sur un document extérieur) : nous
sommes exactement dans le même cas du commit fait précédemment à partir d’une version ancienne.
Bref pour revenir à la dernière version d’une branche, il ne faut pas utiliser le SHA-1 mais le pointeur de
branche (c’est la deuxième et bonne solution).

5.4.4 Revenir à la dernière version : bonne solution

La bonne commande est la suivante :

Notons que l’affichage nous dit qu’on bascule sur la branche.


Regardons de près la commande “git log” :

Et plus précisément la première ligne :

HEAD et master sont séparés par une flèche (et non plus une virgule) ce qui signifie que HEAD pointe
sur master qui lui-même pointe sur la dernière version. Nous sommes dans la configuration suivante :

G. Subrenat - 04/2021 - 24/70 Dépt Informatique - Université de Poitiers


5.5 Quiz : Fonctionnement détaillé des versions
5 FONCTIONNEMENT DÉTAILLÉ DES VERSIONS

74d1180
d88c921

da57328
b1bea7d

ffcfa7e
master

HEAD

Faisons un nouveau commit :

Et voyons le log :

Nous arrivons donc sur la configuration :


74d1180
d88c921

da57328
b1bea7d

2201dbf
ffcfa7e

master

HEAD

Et tout se passe bien car HEAD a transmis l’ordre au pointeur master de faire le commit ; master s’est
déplacé sur la nouvelle version entraı̂nant avec lui le pointeur HEAD.
En conclusion, pour éviter d’arriver à des configurations non voulues 28 , on peut se fixer la règle suivante :
“lorsqu’on fait un commit, le pointeur HEAD doit désigner un pointeur de branche (tel master) et jamais
directement un SHA-1”.

5.5 Quiz : Fonctionnement détaillé des versions

Réponses page 65.


Question 1
une seule réponse possible
On peut changer le SHA-1 d’une version (ou commit) afin par exemple d’avoir une numérotation plus
logique.
- vrai
- faux
28. Sauf, comme d’habitude, si on sait ce que l’on fait.

G. Subrenat - 04/2021 - 25/70 Dépt Informatique - Université de Poitiers


6 BRANCHES

Question 2
une seule réponse possible
Détruire une branche supprime définitivement toutes les versions qui y sont rattachées.
- vrai
- faux
Question 3
une seule réponse possible
Un pointeur de branche (comme master) désigne toujours le même commit, sinon on risquerait de perdre
des données.
- vrai
- faux
Question 4
une seule réponse possible
Le pointeur HEAD, comme son nom l’indique, désigne toujours le premier commit d’une branche.
- vrai
- faux
Question 5
une seule réponse possible
Sur une branche le chaı̂nage des commit est à l’envers : le premier commit de la liste chaı̂née est le dernier
à avoir été créé.
- vrai
- faux
Question 6
une seule réponse possible
HEAD peut être un pointeur sur un pointeur, mais ça n’a pas de sens.
- vrai
- faux
Question 7
une seule réponse possible
Une mauvaise utilisation du pointeur HEAD peut conduire à un état incohérent du repository.
- vrai
- faux

6 Branches

6.1 Préambule

Le principe des branches est de pouvoir mener de front plusieurs versions du logiciel sans qu’elles influent
l’une sur l’autre. Voici quelques exemples pour en appréhender l’intérêt :
- explorer une extension sans connaı̂tre a priori sa faisabilité, et donc sans “polluer” le code principal
- avoir une version de production et une version de développement
- avoir une branche par fonctionnalité, i.e. un espace indépendant pour la développer et la tester
- ...
Voir aussi la notion de workflow.
En règle générale, lorsque le développement d’une branche est terminée, cette dernière est fusionnée avec
une autre, par exemple la branche principale.
À l’issue d’une fusion, si les deux branches ont modifié la même partie d’un fichier, un conflit peut
apparaı̂tre ; c’est alors au programmeur effectuant la fusion de gérer les codes contradictoires.

G. Subrenat - 04/2021 - 26/70 Dépt Informatique - Université de Poitiers


6.2 Création d’une branche 6 BRANCHES

6.2 Création d’une branche

6.2.1 Point de départ

Repartons de notre dernière configuration :


da57328

2201dbf
...

master

HEAD

6.2.2 Création

Créons une branche par exemple pour faire une version C++ de hello world. Et appelons cette branche
cplus :

Nous avons alors le schéma suivant :

cplus
da57328

2201dbf

...

master

HEAD

Une branche est tout simplement une nouvelle étiquette, mais qui pourra avoir ses propres commit.

6.2.3 Changer la branche courante

Mais nous sommes toujours sur la branche initiale ; voici la commande pour changer la branche courante :

Le schéma évolue ainsi :

G. Subrenat - 04/2021 - 27/70 Dépt Informatique - Université de Poitiers


6.2 Création d’une branche 6 BRANCHES

HEAD

cplus
da57328

2201dbf
...

master

Il s’agit de la même commande que pour revenir à un commit antérieur : checkout a pour utilité générale
de se déplacer dans l’arbre des versions.
Une dernière vérification :

avec les mêmes informations : la branche courante (HEAD) est bien cplus, et pour l’instant la branche
master est au même endroit.

6.2.4 Nouveau commit

Dans cette nouvelle branche, créons une version C++ du programme :

et ajoutons la au repository :

Graphiquement nous avons le schéma :

G. Subrenat - 04/2021 - 28/70 Dépt Informatique - Université de Poitiers


6.2 Création d’une branche 6 BRANCHES

HEAD

cplus

649ac99
da57328

2201dbf

...

master

Seule la branche cplus a avancé.

6.2.5 Deuxième commit

Pour faire bonne mesure dans cette branche, rajoutons un commit par exemple pour faire un Makefile :

Avec le nouveau schéma :

HEAD

cplus
2b786e4
649ac99
da57328

2201dbf

...

master

G. Subrenat - 04/2021 - 29/70 Dépt Informatique - Université de Poitiers


6.2 Création d’une branche 6 BRANCHES

6.2.6 Retour sur la branche master

Il faut repositionner HEAD sur l’étiquette master :

Avec le schéma :

cplus

2b786e4
649ac99
da57328

2201dbf

...

master

HEAD

Avec une vérification textuelle :

Et une deuxième :

Notamment on s’aperçoit que le répertoire C++ n’est pas visible dans cette version.

6.2.7 Un commit sur la branche master

Ajoutons une nouvelle fonctionnalité dans la branche master, par exemple pour avoir une fonction qui
souligne un texte :

Avec le schéma :

G. Subrenat - 04/2021 - 30/70 Dépt Informatique - Université de Poitiers


6.3 Quelques commandes 6 BRANCHES

cplus

2b786e4
649ac99
da57328

7b6e894
2201dbf
...

master

HEAD

Les deux branches sont (enfin) visuellement séparées. Et le résultat textuel :

On note le rendu graphique en mode ASCII de l’arborescence. Et voici un rendu avec gitkraken 29 :

6.3 Quelques commandes

6.3.1 Commandes de base

Créer une branche :


 
$ git branch <nom branche>
 
Changer de branche :
 
$ git checkout <nom branche cible>
 
Créer une branche et se déplacer dessus :
29. http ://[Link]

G. Subrenat - 04/2021 - 31/70 Dépt Informatique - Université de Poitiers


6.4 Fusion 6 BRANCHES

 
$ git checkout -b <nom branche>
 

6.3.2 Commandes risquées

Ces commandes peuvent mener à des pertes d’informations ou à des commit orphelins.
Elles sont particulièrement risquées 30 si plusieurs programmeurs travaillent sur le même projet.
Renommer la branche courante :
 
$ git branch -m <nouveau nom>
 
Note : on peut aussi renommer une branche distante.
Supprimer une branche fusionnée :
 
$ git branch -d <nom branche>
 
Note : la branche supprimée ne doit pas être la branche courante.
Note : avec l’option -D, il est possible de supprimer une branche non fusionnée ; on crée alors des orphelins.
La commande fsck permet de lister les commit orphelins. La commande checkout permet de les récupérer.

6.4 Fusion

Lorsqu’une branche arrive à son terme, i.e. que la programmation de la fonctionnalité est terminée, il est
nécessaire de la réintégrer dans une branche que l’on qualifiera de “principale” : c’est la fusion.
Si les deux branches ont modifié des fichiers différents, Git gère de manière autonome la fusion. Même si
les deux branches ont modifié le même fichier, mais à des endroits différents, Git reste autonome.
En revanche, si les deux branches ont modifié la même partie du fichier, Git est incapable de prendre une
décision : c’est au développeur faisant la fusion de gérer le conflit.
La démarche classique d’une fusion est la suivante :
- on choisit la branche qui va recevoir la fusion et donc être modifiée ; généralement on choisit la
branche dite “principale” (master ou develop par exemple).
- on indique le nom de la branche distante dont on veut récupérer les modifications.
- un nouveau commit est créé sur la branche courante.
- la branche distante n’est pas modifiée.
- on vérifie que le projet fonctionne toujours.
30. et donc déconseillées

G. Subrenat - 04/2021 - 32/70 Dépt Informatique - Université de Poitiers


6.4 Fusion 6 BRANCHES

6.4.1 Fusion sans conflit

Reprenons la dernière configuration :

cplus

2b786e4
649ac99
da57328

7b6e894
2201dbf

...

master

HEAD

La branche courante est master et on veut y intégrer le code de cplus.


La fusion s’effectue ainsi :

Les deux fichiers créés dans la branche cplus sont intégrés dans la branche master. Le schéma devient :

cplus
2b786e4
649ac99
da57328

7b6e894
2201dbf

27fd381

...

master

HEAD

La branche master a été complétée avec un nouveau commit, alors que la branche cplus est restée in-
changée.
Avec une vérification textuelle :

G. Subrenat - 04/2021 - 33/70 Dépt Informatique - Université de Poitiers


6.4 Fusion 6 BRANCHES

Même s’il n’y a pas eu de conflit, il faut vérifier que le projet est toujours opérationnel.
Pour résumer le cas d’une fusion sans conflit :
- la fusion s’effectue dans la branche courante avec la commande :
 
$ git merge <nom branche distante>
 
- un nouveau commit est créé sur la branche courante
- la branche distante reste inchangée

6.4.2 Fusion sans conflit : fast forward

Il y a un cas où aucun nouveau commit n’est créé lors de la fusion : lorsque la branche courante n’a pas
progressé depuis la création de la branche distante. Dans ce cas l’étiquette de la branche courante est
simplement déplacée au même niveau que la branche distante.
Supposons que l’on ait le schéma suivant :

cplus
2b786e4
649ac99
da57328

2201dbf

...

master

HEAD

On fait une fusion :


 
$ git merge cplus
 
On obtient alors le schéma :

G. Subrenat - 04/2021 - 34/70 Dépt Informatique - Université de Poitiers


6.4 Fusion 6 BRANCHES

cplus

2b786e4
649ac99
master
da57328

2201dbf
...
HEAD

Donc sans création d’un nouveau commit.


Il est cependant possible de forcer la création d’un commit avec l’option : --no-ff :
 
$ git merge --no-ff cplus
 
On obtient alors le schéma :

cplus
2b786e4
649ac99
da57328

2201dbf

5aa33ae

...

master

HEAD

Avec création d’un nouveau commit.


Et le schéma en mode textuel :

On peut vérifier que le nouveau commit a les mêmes informations que la branche cplus :

6.4.3 Fusion avec conflit

Lorsqu’il y a un conflit, le problème doit être résolu manuellement par le développeur faisant la fusion :
- soit il privilégie une des deux branches
- soit il mélange les deux

G. Subrenat - 04/2021 - 35/70 Dépt Informatique - Université de Poitiers


6.4 Fusion 6 BRANCHES

Dans tous les cas il vérifie et teste le code.


Très souvent, lorsqu’il y a un conflit, la cause provient d’une mauvaise gestion du projet.
Nous allons provoquer un conflit avec notre exemple :
- création d’une branche typo qui va renommer la fonction underline en souligner
- la branche master qui va renommer la fonction underline en soulignement
- on fusionne la branche typo dans la branche master
Après les modifications dans les deux branches et avant la fusion, nous avons le schéma suivant :

typo

2e0fb2c

...
5aa33ae

2ccf231

...

master

HEAD

Il y a un conflit dans les trois fichiers : hello.c, manip.h et manip.c.


Lançons la fusion :

Le message est en accord avec notre analyse.


Et le système nous dit :

Ce qui est en cohérence avec le message précédent.


Les fichiers incriminés contiennent des marqueurs pour visualiser les zones de conflit. Prenons l’exemple
du fichier manip.h :

G. Subrenat - 04/2021 - 36/70 Dépt Informatique - Université de Poitiers


6.4 Fusion 6 BRANCHES

Les deux autres fichiers ont les mêmes annotations.


On voit que :
- les lignes 7 et 9 sont en conflit
- la ligne 7 vient de la branche master
- la ligne 9 vient de la branche typo
En l’occurrence nous allons garder la version de la branche typo en supprimant les lignes 6, 7, 8 et 10.
La même chose est faite pour les deux autres fichiers. Après un test de bon fonctionnement (on rappelle
qu’on fait un commit uniquement sur un code fonctionnel), il reste à faire un add et un commit :

Il est à noter qu’un message est proposé par défaut pour le commit.
Nous avons alors le schéma suivant :

typo
2e0fb2c

...
6c3b4ea
5aa33ae

2ccf231

...

master

HEAD

Avec la vérification textuelle :

6.4.4 Quelques commandes

Annuler une fusion (avant le commit) :


 
$ git merge --abort
 
Résoudre graphiquement un conflit :
 
$ git mergetool
 

G. Subrenat - 04/2021 - 37/70 Dépt Informatique - Université de Poitiers


6.5 J’ai une urgence 6 BRANCHES

Il est nécessaire d’avoir au préalable installé un outil (tel kdiff3 par exemple).
Fusionner deux branches en gardant une structure linéaire (rejouer des commit) :
 
$ git rebase <nom branche distante>
 
C’est extrêmement dangereux, particulièrement dans un travail à plusieurs.
Renommer la branche courante :
 
$ git branch -m <nouveau nom>
 
Note : on peut aussi renommer une branche distante.

6.5 J’ai une urgence

Voici le scénario :
- vous avez commencé à travailler sur une branche
- votre patron arrive avec une urgence à développer ... sur la branche courante
- il n’est pas possible de faire de commit
- que faire ?
La commande stash 31 est faite pour cela :
 
$ git stash
 
Cette commande sauvegarde et met de côté tous les changements depuis le dernier commit, puis revient
à l’état initial du commit.
Attention les nouveaux fichiers non traqués sont exclus de cette sauvegarde.
Pour récupérer les changements :
 
$ git stash pop
 
Il est possible qu’il y ait des conflits
Les commandes “git stash” sont empilables.

6.6 Quiz : Branches

Réponses page 66.


Question 1
une seule réponse possible
Les branches sont très complexes à utiliser et sont de fait rarement utilisées.
- vrai
- faux
Question 2
une seule réponse possible
Quelle commande permet de créer une branche ?
- git add branch ...
- git branch add ...
- git create branch ...
- git branch create ...
- git branch --create ...
- git branch ...
Question 3
une seule réponse possible
Quelle commande permet de changer la branche courante ?
31. [Link] Stach

G. Subrenat - 04/2021 - 38/70 Dépt Informatique - Université de Poitiers


6.6 Quiz : Branches 6 BRANCHES

- git branch --change ...


- git branch --checkout ...
- git checkout ...
- git checkout --branch ...
Question 4
une seule réponse possible
On peut créer une nouvelle branche uniquement à partir du commit le plus récent d’une branche existante ?
- vrai
- faux
Question 5
plusieurs réponses possibles
Sachant qu’une branche est identifiée par une étiquette/pointeur sur son commit le plus récent, supprimer
ce pointeur est catastrophique.
- oui
- oui mais non
- non
Question 6
une seule réponse possible
Pour supprimer le dernier commit d’une branche, il suffit de reculer l’étiquette portant le nom de la
branche d’un cran.
- vrai
- faux
Question 7
une seule réponse possible
Supprimer une branche permet de libérer de la place disque ?
- vrai
- faux
Question 8
une seule réponse possible
Lors d’une fusion, Git arrive souvent à rassembler les codes des deux branches de manière autonome ?
- vrai
- faux
Question 9
une seule réponse possible
On peut fusionner 3 branches ou plus simultanément ?
- vrai
- faux
Question 10
plusieurs réponses possibles
Dans une fusion, à quelle branche rajoute-t-on un commit ?
- la branche courante
- la branche distante
- aucune
Question 11
une seule réponse possible
En cas de conflit, le développeur doit choisir une des deux branches et éliminer l’autre ?
- vrai
- faux
Question 12
une seule réponse possible

G. Subrenat - 04/2021 - 39/70 Dépt Informatique - Université de Poitiers


7 REPOSITORIES DISTANTS

La commande “git stash” permet de :


- supprimer les modifications apportées depuis le dernier commit
- sauvegarder les modifications apportées depuis le dernier commit et revenir à la situation de celui-ci.

7 Repositories distants
Avertissement : le discours de cette section est orienté par une vision centralisée de l’utilisation de Git.
Dès que l’on veut travailler à plusieurs, il faut avoir un site d’hébergement commun (dit repository distant)
où chaque développeur va pouvoir déposer ses contributions et récupérer celles des autres.
Un repository local (a priori un seul par développeur) est une copie du repository distant afin de pouvoir
travailler sans perturber les autres développeurs.
Un repository local peut être, par rapport au repository distant, à la fois :
- en retard car les autres développeurs ont ajouté des contributions non encore rapatriées en local,
- en avance car les contributions locales n’ont pas encore été envoyées sur le repository distant.
Un repository local doit donc faire des synchronisations régulières avec le repository distant... avec les
conflits qui vont avec.

7.1 Créer et paramétrer un compte

Il existe quantité d’hébergeurs de projets Git, généralement ils proposent plus qu’un dépôt Git : tickets,
intégration continue, ... Certains sont gratuits, d’autres sont gratuits uniquement en version limitée.
Nous allons illustrer la création d’un compte avec le site [Link] Si vous choisissez un autre
hébergeur la démarche sera similaire.

7.1.1 Création

Via l’entrée “Sign in”, puis “Register now”, créer un compte est simple et ne nécessite de fournir que peu
d’informations.
La page de configuration est accessible par l’icône en haut à droite et l’entrée “Edit profile”.
On peut, dans cette page, noter les entrées suivantes :
- “Profile” qui permet de paramétrer le compte avec notamment :
- l’email utilisé pour les commit (une adresse privée est fournie)
- quelles informations sont visibles des autres internautes
- SSH Keys qui permet de gérer les clés SSH (cf. ci-dessous)
Dans le menu accessible par l’icône en haut à droite, si on choisit l’entrée avec son nom, on arrive sur
page de statistiques sur son activité.

7.1.2 Générer les clés SSH

Pour accéder à son compte via le protocole SSH, il faut créer une paire de clés et déposer la clé publique
sur le site de gitlab.
Voici la démarche, sous Linux, pour créer une paire de clés (la démarche sur les autres systèmes 32 est
similaire).
Pour créer une paire de clés :
32. Sous Windows il existe l’application “Git Bash” qui est une console de commandes améliorée, ou encore “putty”.

G. Subrenat - 04/2021 - 40/70 Dépt Informatique - Université de Poitiers


7.2 Création et initialisation d’un projet 7 REPOSITORIES DISTANTS

Dans le répertoire $HOME/.ssh les fichiers id rsa (clé privée) et id [Link] (clé publique) ont été créés.
C’est le fichier id [Link] 33 qu’il faut déposer sur le compte gitlab. Voici le contenu du répertoire .ssh :

On note que le répertoire .ssh et le fichier id rsa ne sont lisibles que par le propriétaire du compte.
Dans la génération des clés, la passphrase a été laissée vide. Cela nous facilitera la vie par la suite, mais
on supprime une couche de sécurité.
Pour gérer de manière quasi-transparente une passphrase, reportez-vous aux commandes ssh-agent et
ssh-add.

7.1.3 Enregistrer la clé SSH dans gitlab

Les clés SSH sont gérées par :


- menu personnel (icône en haut à droite) entrée “Edit profile”
- entrée “SSH Keys” (partie gauche de l’écran)
Ensuite :
- il faut recopier le contenu du fichier id [Link] (et surtout pas l’autre 34 ) dans la zone de saisie
- donner un titre parlant
- éventuellement préciser une date d’expiration
- valider
Si vous avez des comptes sur plusieurs machines, il faut répéter cette configuration pour chaque compte.
Cet échange de clé vous permettra d’accéder aux dépôts de gitlab, à partir de votre machine personnelle,
sans vous authentifier 35 .

7.2 Création et initialisation d’un projet

7.2.1 Repository distant

Chez l’hébergeur (gitlab pour nous), il suffit de créer un projet blanc (i.e. vide) : “Create blank project”.
Pour la configuration, il faut :
- donner un nom
- donner une description
- indiquer s’il est public ou privé
33. et surtout pas l’autre qui doit rester secret pour éviter des usurpations d’identité
34. cf. note précédente
35. C’est un abus de langage, on entend par là “sans taper de mot de passe”.

G. Subrenat - 04/2021 - 41/70 Dépt Informatique - Université de Poitiers


7.2 Création et initialisation d’un projet 7 REPOSITORIES DISTANTS

Un projet public sera accessible, en lecture, par tout internaute.


Un projet privé qui n’est visible que par son créateur.
Il est ensuite possible d’ajouter d’autres membres (qui doivent avoir un compte chez l’hébergeur) qui
participeront à l’évolution du projet.
Pour illustrer ce TP, j’ai créé un projet nommé “tp-git” et qui est public.
Pour le récupérer (cf. ci-après pour la commande clone) :
- sans compte gitlab :
 
$ git clone [Link]
 
- avec un compte gitlab :
 
$ git clone git@[Link]:subrenat/[Link]
 

Il contient toutes les opérations pratiquées jusqu’ici avec les mêmes sha1 (cf. ci-dessous).

7.2.2 Initialisation

Cette section est juste présente pour information et n’est pas utile pour la suite.
En règle générale la génération d’un projet vide est suffisante.
Mais dans notre cas nous avons travaillé avec un repository purement local, et il sera utile qu’il soit relié
à un repository distant 36 .
Il n’y a que deux commandes 37 à saisir (après avoir déposé la clé ssh), commandes fournies par gitlab à
la suite de la création d’un projet vide :

La première commande crée le repository distant, et la seconde le synchronise, pour les branches, avec le
repository local.
Ce qui nous intéresse, c’est que nos trois branches ont bien été prises en compte dans le repository distant
(que l’on a appelé, par convention et par défaut, origin).
Voici l’interface de gitlab :

36. en l’occurrence pour qu’il soit accessible par les lecteurs de ce document.
37. On rajoute “git push -u origin –tags” si des tags ont été créés.

G. Subrenat - 04/2021 - 42/70 Dépt Informatique - Université de Poitiers


7.3 Cloner un dépôt 7 REPOSITORIES DISTANTS

7.3 Cloner un dépôt

7.3.1 Clonage

Cette opération est à faire une seule fois, pour un développeur, lorsque celui-ci rejoint un projet. Il doit
rapatrier le repository distant pour en faire une version locale : le clonage.
Syntaxe :
 
$ git clone <url repository distant> [<répertoire local>]
 
Il existe plusieurs protocoles pour l’url du repository distant : ssh, git, https, ...
Si le nom du répertoire n’est pas fourni, il est déduit du nom du repository.
Pour la suite, nous aurons deux utilisateurs pour illustrer les interactions multiples :
- Gilles travaillant dans le répertoire local PROJET C
- Sellig travaillant dans le répertoire local TEJORP C
Pour le premier utilisateur, son dépôt local est déjà configuré. car c’est lui qui nous a servi d’exemple
jusqu’à présent et qui nous a permis d’initialiser le repository distant.
Pour le deuxième, il faut faire un clone :

Pour les captures d’écran des consoles de commandes, la charte graphique est la suivante :
- utilisateur gilles travaille dans le répertoire PROJET C et le prompt est vert.
- utilisateur sellig travaille dans le répertoire TEJORP C et le prompt est bleu.
Lorsqu’on regarde l’état du dépôt, il y a une information supplémentaire.
Avant, lorsqu’il n’y avait pas de repository distant :

et :

Maintenant, avec le repository distant :

et :

Avec l’affichage du status, il y a une ligne supplémentaire indiquant si on est synchronisé avec le repository
distant.

G. Subrenat - 04/2021 - 43/70 Dépt Informatique - Université de Poitiers


7.3 Cloner un dépôt 7 REPOSITORIES DISTANTS

Dans le graphe, on s’aperçoit que chaque branche locale (notée en vert) est associée à une branche distante
(notée en rouge).
Et voyons le nouvel utilisateur, avec le repository distant :

et :

Le graphe est légèrement différent : toutes les branches distantes n’ont pas (encore) leurs équivalents
locaux.

7.3.2 Configuration et fonctionnement

Ne pas oublier de configurer le dépôt local :


 
sellig@maison:TEJORP_C$ git config [Link] "sellig@[Link]"
sellig@maison:TEJORP_C$ git config [Link] "Sellig"
sellig@maison:TEJORP_C$ git config [Link] gedit
sellig@maison:TEJORP_C$ git config [Link] true
 
38
Le dépôt local contient tout l’historique du projet . Si le repository distant venait à disparaı̂tre, les
données ne seraient pas perdues.
Le développeur peut envoyer ses contributions sur le repository distant (commande push), et récupérer
les contributions des autres développeurs (commande pull).

7.3.3 Quelques commandes

Pour avoir une copie locale d’un repository distant :


 
$ git clone <url repository distant> [<répertoire local>]
 
Lister les dépôts distants :
 
$ git remote -v
 

Et quelques commandes à manipuler avec attention :


- Ajouter un dépôt distant :
 
$ git remote add <nom du dép^
ot> <url>
 
- Renommer un dépôt distant :
 
$ git rename <ancien nom> <nouveau nom>
 
- Changer l’url d’un dépôt distant :
 
$ git remote set-url <nom du dép^
ot> <url>
 
- Supprimer un dépôt distant :
 
$ git remote remove <nom du dép^
ot>
 

38. à confirmer, c’est peut-être plus subtil que cela

G. Subrenat - 04/2021 - 44/70 Dépt Informatique - Université de Poitiers


7.4 Principe de fonctionnement 7 REPOSITORIES DISTANTS

7.4 Principe de fonctionnement

Répétons l’hypothèse simplificatrice : nous nous plaçons dans un modèle centralisé : il y a un repository
distant qui sert de référence et qui est alimenté par les repositories locaux des développeurs.
Mais Git peut être décentralisé et donc avoir plusieurs repositories distants.
Un développeur suit le scénario général suivant :
- Il récupère la dernière version du logiciel en provenance du repository distant (commande “git pull”)
dans son repository local.
- Il effectue des modifications en local
- Il crée une nouvelle version (commande “git commit”) toujours en local
- Éventuellement il fait plusieurs cycles modification/commit.
- Il envoie ses nouvelles versions sur repository distant (commande “git push” 39 ) pour les rendre
disponibles à la communauté
- Ce scénario est répété continûment.
Mais plusieurs problèmes viennent se greffer :
- il y a plusieurs branches à gérer
- pendant qu’un développeur fait des modifications en local, le repository distant peut évoluer par le
fait d’autres développeurs :
- ajout de nouvelles version, possiblement sur la branche que le développeur modifie : risque de
conflits
- ajout ou suppression de branches
- ...

7.5 Les branches

7.5.1 Introduction

En règle générale, à une branche locale correspond une branche sur le repository distant qui a le même
nom précédé du nom du repository. Par exemple, en prenant le nom classique “origin” pour le repository
distant, voici ce qu’on peut avoir :
- Repository local, il y a les branches : master et develop (c’est un choix “arbitraire” 40 pour illustrer)
- Repository distant il y a les branches : “origin/master” et “origin/develop”
- Repository local il y a également les branches : “origin/master” et “origin/develop” qui sont une
copie locale des mêmes branches distantes en mode read only.
Pourquoi n’y a-t-il pas uniquement un seul jeu de branches ?
On pourrait imaginer que la branche “develop” (par exemple) soit partagée par tous les développeurs.
Un premier soucis purement technique est qu’il faudrait une connexion internet permanente.
Mais surtout le deuxième soucis est que la branche changerait en permanence si un grand nombre de
développeurs sont simultanés dessus. On ne peut pas imaginer travailler dans un répertoire évoluant en
permanence avec des codes extérieurs en cours de débugage.
Donc il faut d’une part la branche “develop” en local pour travailler dans un environnement stable et
une branche sur le repository distant pour partager le code. Lorsque le travail en local est terminé on le
commit sur le branche locale, et on fusionne cette dernière dans la branche distante.
Pourquoi a-t-on une copie de la branche distante en local ?
C’est à étudier, il y a plus que certainement de bonnes raisons !
Revenons sur la commande push où on met à jour le repository distant. Le problème est que le temps
de développer sa fonctionnalité, la branche distante a pu changer, par un autre développeur, rendant
l’injection des commit problématique.
Aussi généralement refait-on un pull pour fusionner les dernières modifications distantes dans sa branche
locale. Les conflits éventuels réglés, le push est alors possible 41 .
39. nous verrons qu’il est préférable de faire un “pull” avant le push
40. pas vraiment en fait, cf. section sur le workflow
41. En espérant qu’entre temps la branche distante n’est pas été modifiée encore une fois

G. Subrenat - 04/2021 - 45/70 Dépt Informatique - Université de Poitiers


7.5 Les branches 7 REPOSITORIES DISTANTS

Quelques commandes sont présentées dans la section suivantes. S’ensuivront quelques exemples illustratifs.

7.5.2 Quelques commandes

a) branches distantes
Pour visualiser les branches sur le repository distant :
 
$ git branch -r
 
Attention, il peut être nécessaire de faire un pull au préalable pour récupérer les dernières informations
du repository distant : en effet cette commande liste les copies locales des branches distantes.

b) Récupérer les informations du dépôt distant


Pour récupérer les dernières versions du repository distant et les fusionner au repository local :
 
$ git pull [<nom du dép^
ot> [<nom branche 1> ...]]
 
Si le nom du dépôt n’est pas précisé, c’est celui par défaut qui est choisi (généralement “origin”).
Si aucun nom de branche n’est précisé, c’est la branche courante qui est mise à jour.
Ce sont les données de la branche distante qui sont intégrées en local. Il s’agit donc d’une fusion avec la
gestion qui en découle (i.e. conflits éventuels).
En réalité, la commande pull est la succession de deux commandes :
- fetch qui recopie la branche distante dans son alter ego local
- merge qui fusionne la version locale de la branche distante dans la branche locale
Par exemple, si la branche courante est develop, les trois commandes suivantes sont équivalentes 42 :
 
$ git pull

 

$ git pull origin

 

$ git pull origin develop
 
et reviennent à saisir successivement les deux commandes suivantes :
 
$ git fetch origin develop
 
qui recopie la version distante de origin/develop dans la version locale de origin/develop, mais sans
modifier la branche locale develop. Et on ajoute la commande :
 
$ git merge origin/develop
 
qui fusionne la version locale de origin/develop dans la branche locale develop.
Il s’agit bien d’une fusion avec des conflits potentiels.

c) Mettre à jour le dépôt distant


Il s’agit cette fois de mettre à jour une branche distante avec ses propres modifications locales.
Comme la branche distante a pu être modifiée depuis le dernier pull (ce qui empêcherait une mise à jour),
il est préférable de refaire un pull (cf. ci-dessus).
Une fois le pull effectué, la commande est la suivante :
 
$ git push [<nom du dép^
ot> [<nom branche 1> ...]]
 
42. en supposant que le repository par défaut est origin

G. Subrenat - 04/2021 - 46/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

Si le nom du dépôt n’est pas précisé, c’est celui par défaut qui est choisi (généralement “origin”).
Si aucun nom de branche n’est précisé, c’est la branche courante qui va être renvoyée sur le repository
distant.
La commande :
 
$ git push origin --tags
 
envoie tous les tags sur le repository distant (cf. “git help tag”).

d) Créer une nouvelle branche


Nous avons déjà vu comment créer une branche dans le repository local avec une des deux commandes
suivantes :
 
$ git branch <nom branche>

 

$ git checkout -b <nom branche>
 
Mais cela ne suffit pas pour créer la branche équivalente sur le repository distant ; autrement dit un simple
push ne le fera pas.
Il faut donc la créer explicitement sur le repository distante :
 
$ git push -u <nom du dép^
ot> <nom de la branche>
 
Par exemple :
 
$ git branch design
$ git push -u origin design
 
Une fois ces commandes effectuées, les mises à jour distantes se feront avec les push/pull habituels.
Les autres développeurs récupéreront automatiquement la nouvelle branche lors de leur prochain pull.

d) Supprimer une branche


De même que pour la création, une branche doit être supprimée en local et sur le repository distant.
Le développeur décidant de supprimer une branche doit :
- supprimer la branche locale avec une des deux commandes suivantes :
 
$ git branch -d <nom branche>

 

$ git branch -D <nom branche>
 
- supprimer la branche distante duale :
 
$ git push <nom dép^
ot> --delete <nom branche>
 

Les autres développeurs doivent :


- explicitement prendre en compte la destruction des branches distantes :
 
$ git fetch --prune
 
- supprimer à la main les branches locales avec une des deux commandes suivantes :
 
$ git branch -d <nom branche>

 

$ git branch -D <nom branche>
 
:

7.6 Quelques exemples

Le but est de choisir quelques scénarios typiques de travail et de les illustrer pas à pas.

G. Subrenat - 04/2021 - 47/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

7.6.1 Tout se passe bien

Voici l’enchaı̂nement temporel des opérations :


- les deux développeurs n’ont aucun travail en cours
- le premier fait un développement et l’envoie sur le repository distant
- le second n’intervient qu’après
- donc pas de conflit
a) le premier récupère la dernière version du repository

b) le premier ajoute une fonctionnalité sur la branche master

c) le premier intègre la fonctionnalité dans la branche locale


On vérifie que l’état du repository est cohérent :

Intégration :

Une dernière vérification :

On en profite pour insister :


- la branche locale (master) a un commit de plus (6804640)
- la branche distante (origin/master) a un cran de retard car le push n’est pas encore fait.
On peut le vérifier :

G. Subrenat - 04/2021 - 48/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

Le message de la deuxième ligne est explicite.


d) le premier met à jour la branche distante

Note : la commande aurait pu être “git push origin master”

e) le second met à jour le repository local

On note que que le repository local n’est pas au courant des changements distants tant que la commande
suivante n’est pas lancée :

Note : la commande aurait pu être “git pull origin master”

Le repository local du deuxième développeur en est au même point que celui du premier développeur.
f ) le second ajoute une fonctionnalité

g) le second intègre la fonctionnalité dans la branche locale

G. Subrenat - 04/2021 - 49/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

h) le second met à jour la branche distante

i) le premier récupère la dernière version du repository

Et tout est en ordre.

7.6.2 Deux push simultanés

Voici l’enchaı̂nement temporel des opérations :


- les deux développeurs ont la dernière version du repository distant
- en “même temps” les deux développeurs ajoute une fonctionnalité, et les deux fonctionnalités sont
indépendantes (i.e. elles n’entrent pas en conflit)
- en “même temps” ils font un commit
- en “même temps” ils font un pull
- en premier, le premier développeur fait un push
- en second, le second développeur fait un push
- il y a donc un décalage, pour le second développeur, sur la branche distante
a) les deux sont à jour par rapport au repository distant :

b) les deux ajoutent une fonctionnalité :

G. Subrenat - 04/2021 - 50/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

c) les deux font leur commit :

d) les deux font leur pull précurseur du push :

e) le premier est plus rapide et met à jour la branche distante :

Tout se passe bien car la branche distante n’a pas été modifiée depuis le dernier pull.
f ) le second veut à son tour mettre à jour la branche distante :

En l’occurrence le message est clair : un autre développeur à modifié la branche distante.


g) le second doit refaire un pull pour récupérer la dernière version de la branche distante :

Une fusion est effectuée entre la nouvelle version distante et la version locale (avec un nouveau sha1) :

G. Subrenat - 04/2021 - 51/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

h) un nouveau push :
Comme la fusion ne pose pas de problème, un push est désormais possible 43 :

Et cette fois-ci, tout s’est déroulé correctement.

i) et le premier développeur peut récupérer la nouvelle version :

7.6.3 Récupérer les changements d’une branche

Voici l’enchaı̂nement temporel des opérations :


- les deux développeurs n’ont aucun travail en cours et ont la dernière version du repository
- il y a deux branches : master et develop
- le premier fait un ajout sur la branche develop et l’envoie sur le repository distant
- le second a pour branche courante master et fait un pull
La différence avec le premier exemple est donc que le développeur faisant un pull n’est pas sur la branche
qui vient d’être modifiée.
a) état des deux repositories locaux :
Pour le premier développeur qui est sur la branche develop :
43. sauf si la branche distante a encore évolué

G. Subrenat - 04/2021 - 52/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

Et le second développeur est sur la branche master :

b) le premier développeur ajoute une fonctionnalité sur la branche develop :

Ce qui donne graphiquement :

c) le second développeur fait un pull en étant sur la branche master :

On note le message indiquant une nouvelle version dans la branche develop.


d) le seconde développeur regard l’état du repository :
Avec l’interface textuelle :

G. Subrenat - 04/2021 - 53/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

On a ajouté l’option --all pour ne pas avoir un message tronqué.


Avec l’interface graphique, on obtient les mêmes informations :

On voit que la branche distante est en avance d’un cran sur la branche locale.
e) le second développeur se déplace sur develop :

On note que le message indique que le pull précédent n’a pas mis à jour la branche locale.

f ) le second développeur fait un nouveau pull pour mettre à jour la branche develop :

Avec une vérification graphique/textuelle 44 :

La branche locale et la branche distante sont bien au même niveau.


Il faut donc bien noter qu’un pull ne met à jour complètement que la branche courante.

7.6.4 Suppression définitive d’une branche

Supprimer une branche, n’est pas trivial :


- Elle se trouve en 3 exemplaires :
- dans le repository distant
- dans le repository local : la copie de la branche distante
44. l’interface textuelle est plus explicite dans ce cas

G. Subrenat - 04/2021 - 54/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

- dans le repository local : la branche locale


- Les autres développeurs doivent également faires des opérations spécifiques
Notez que le terme “définitif” est incorrect : la branche n’apparaı̂tra plus dans les affichages mais elle
sera toujours présente dans le repository sous forme de commit orphelins.
Nous reprenons le dépôt sandbox précédent pour supprimer la branche develop.
a) Les deux développeurs sont sur la branche master et c’est la branche develop qui doit disparaı̂tre.

b) le premier développeur supprime la branche distante :

On note la syntaxe particulière 45 .


La branche est déjà supprimée sur le repository distant et les autres développeurs en seront notifiés lors
de leurs prochains pull.
On le vérifie :

La branche est bien absente du repository distant.

La copie locale de la branche distante a également disparu.


c) le premier développeur supprime la branche locale :

Donc les commit existent toujours mais sont orphelins. Seule la branche master est désormais visible :

d) La démarche effectuée jusque là est relativement intuitive. Mais les autres développeurs doivent faire
des actions particulières, sinon on court le risque de recréer par inadvertance la branche distante.
45. avant la version 1.7, la syntaxe était “git push origin:develop”

G. Subrenat - 04/2021 - 55/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

e) le second développeur fait un pull

Aucun message n’indique qu’une branche a disparu.


On regarde les branches distantes :

La branche distante semble toujours exister.


f ) le second développeur passe sur la branche develop :

Toujours aucune indication de la suppression de la branche distante.


g) à ce stade, il n’est pas exclu qu’un commit/push puisse recréer la branche distante, à étudier.
h) le second développeur veut ajouter une fonctionnalité sur la branche develop ; il fait donc un pull pour
avoir la dernière version :

On a enfin l’indication que la branche distante n’existe plus.


i) le second développeur indique de retirer les copies locales des branches distantes qui n’existent plus
dans le repository distant :

La branche distante a bien disparu.


j) il ne reste plus qu’à supprimer la branche locale :

La suppression est complète.

G. Subrenat - 04/2021 - 56/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

Pour résumer :
- le développeur qui détruit la branche :
 
$ git push origin --delete <nom branche>
$ git branch -D <nom branche>
 
- les autres développeurs :
 
$ git fetch --prune
$ git branch -D <nom branche>
 

7.6.5 Création d’une nouvelle branche

Créer une nouvelle branche est plus intuitif que la suppression. Temporellement :
- le premier développeur crée la branche (versions locale et distante).
- le second développeur la récupère.
a) Les deux développeurs sont sur la branche master (la seule qui existe).

b) le premier développeur crée une branche locale partant du premier commit.


On se place tout d’abord sur le premier commit :

puis on crée la branche :

La nouvelle branche apparaı̂t bien en local, mais la branche distante n’existe pas encore.
c) le premier développeur crée la branche distante correspondante :

avec une vérification :

G. Subrenat - 04/2021 - 57/70 Dépt Informatique - Université de Poitiers


7.6 Quelques exemples 7 REPOSITORIES DISTANTS

d) le premier développeur ajoute une fonctionnalité pour faire bonne mesure :

Sans oublier le push :

Le travail du premier développeur est terminé :

e) le second développeur récupère la dernière version du repository distante :

Il y a bien l’indication de la nouvelle branche. On vérifie :

f ) Mais la branche locale n’existe pas encore :

Pour la créer un simple checkout est suffisant :

G. Subrenat - 04/2021 - 58/70 Dépt Informatique - Université de Poitiers


7.7 Workflow 7 REPOSITORIES DISTANTS

Pour résumer :
- le développeur qui crée la branche :
 
$ git checkout -b <nom branche>
$ git push --set-upstream origin <nom branche>
 
l’option “-u” est un raccourci de ‘--set-upstream”‘
- les autres développeurs :
 
$ git pull
$ git checkout <nom branche>
 

7.7 Workflow

Le but est d’avoir une stratégie pour utiliser des branches avec des rôles précis,
Un modèle à été proposé par :
[Link]
Branches principales à durée de vie infinie :
- master : branche de production. Elle contient les versions successives livrées.
- develop : branche d’intégration. Elle contient le code destiné à une prochaine release. Lorsque le
code est stable, il est fusionné (merge) dans la branche master, ce qui correspond alors à un nouveau
numéro de version.
Branches secondaires :
- features : branches pour ajouter des fonctionnalités
- release : branche de préparation à une nouvelle version de production
- hotfix : branche de correction des bugs majeurs de la branche de production
Des extensions à la commande git existent pour faciliter la manipulation du workflow :
[Link]

7.8 Quiz : Repositories distants :

Réponses page 68.


Question 1
une seule réponse possible
Pour récupérer un projet hébergé par une plate-forme, il faut avoir un compte sur cette dernière ?
- vrai
- faux
Question 2
une seule réponse possible
La commande clone est la seule manière de créer un projet ?
- vrai
- faux
- la question n’a pas de sens
Question 3
plusieurs réponses possibles

G. Subrenat - 04/2021 - 59/70 Dépt Informatique - Université de Poitiers


7.8 Quiz : Repositories distants : 7 REPOSITORIES DISTANTS

Quelles commandes peuvent donner des informations sur un projet sans le modifier ?
- init
- clone
- status
- log
- push
- pull
- config
- branch
- fetch
- merge
Question 4
une seule réponse possible
Git est un modèle centralisé reposant sur un dépôt distant principal ?
- vrai
- faux
Question 5
une seule réponse possible
Du point de vue d’un développeur, en général une branche est gérée en combien d’exemplaires ?
- 1
- 2
- 3
- 4
Question 6
plusieurs réponses possibles
Quelle(s) commande(s) permet(tent) de lister les branches locales ?
- git branch
- git branch -r
- git branch --verbose
- git branch --list
Question 7
plusieurs réponses possibles
Quelle(s) commande(s) permet(tent) de lister les branches distantes ?
- git branch
- git branch -r
- git branch --verbose
- git branch --list
Question 8
une seule réponse possible
Un tag ressemble à une branche si ce n’est qu’il ne peut pas bouger (on ne peut pas faire de commit
dessus) ?
- vrai
- faux
Question 9
une seule réponse possible
Créer une branche dans le repository local la crée automatiquement dans le repository distant ?
- vrai
- faux
Question 10
une seule réponse possible
Supprimer une branche dans le repository distant la supprime automatiquement dans le repository local ?

G. Subrenat - 04/2021 - 60/70 Dépt Informatique - Université de Poitiers


8 CONCLUSION

- vrai
- faux

8 Conclusion
Il y a beaucoup de chose à dire, mais pour être succinct :
- Git est un outil indispensable à connaı̂tre pour un informaticien.
- Git est un outil complexe.
- Ne jamais dire que l’on maı̂trise Git 46 , c’est le meilleur moyen pour échouer à un entretien d’em-
bauche.
- Plus on progresse dans Git 47 , plus on est conscient de la taille de l’univers 48 .
- Quelle est la première instruction dans un projet ?
Réponse : git init

46. ou C++ d’ailleurs


47. ou C++ d’ailleurs (bis repetita)
48. Chuck Norris a maı̂trisé Git (et C++) ... deux fois

G. Subrenat - 04/2021 - 61/70 Dépt Informatique - Université de Poitiers


9 RÉPONSES AUX QUIZ

9 Réponses aux quiz

9.1 Réponses quiz : Principe de Git

cf. section 2.2, page 4


Question 1
plusieurs réponses possibles
Quel est le rôle de Git ?
- garder un historique de toutes les versions d’un projet
- travailler à plusieurs sur un projet
- faire de la gestion de projet
c’est au mieux une aide à la gestion de projet
Question 2
une seule réponse possible
Il est intéressant d’utiliser Git pour un projet avec un seul développeur.
- vrai
pour la gestion de l’historique
- faux
Question 3
une seule réponse possible
À quelle fréquence crée-t-on des versions ?
- très rarement : un logiciel a très peu de versions dans son existence
On ne parle pas des mêmes versions, et il est possible sous Git, avec des tags, de marquer des
versions particulières (au sens commercial du terme).
- chaque fois qu’un fichier source est définitivement terminé
Un fichier source n’est jamais définitivement terminé.
- une fois par jour pour faire une sauvegarde
Ce n’est pas un logiciel de sauvegarde (même s’il a cette conséquence) et il ne faut versionner que
des états corrects.
- toutes les heures pour ne pas perdre plus d’une heure de travail en cas de panne
Cf. remarque précédente.
- très souvent, chaque fois qu’une fonctionnalité est implémentée et testée
Une version (i.e. un commit) correspond à une et une seule fonctionnalité.
Question 4
une seule réponse possible
Git est très peu utilisé.
- vrai
- faux
Au contraire il est très répandu dans le monde du logiciel et un développeur se doit de le connaı̂tre.
Question 5
une seule réponse possible
Il existe des logiciels comparables à Git.
- vrai
Plus ou moins proches ; Mercurial, Subversion (SVN), CVS, ...
- faux

9.2 Réponses quiz : Initialisation de Git

cf. section 3.6, page 9


Question 1
une seule réponse possible
Un projet géré par Git en local doit toujours être lié à un dépôt distant géré par un serveur.

G. Subrenat - 04/2021 - 62/70 Dépt Informatique - Université de Poitiers


9.3 Réponses quiz : Gestion des versions 9 RÉPONSES AUX QUIZ

- vrai
- faux
Le répertoire de travail peut être le seul dépôt géré par Git, il est alors réservé à un seul utilisateur.
Question 2
plusieurs réponses possibles
Quelle(s) commande(s) permet(tent) d’enregistrer son nom dans Git ?
- git config [Link] ”mon nom”
enregistrement uniquement pour le projet en cours
- git init [Link] ”mon nom”
non, git init sert à créer un projet vide
- git config --global [Link] ”mon nom”
enregistrement pour tous les projets de l’utilisateur
- git init --global [Link] ”mon nom”
cf. deux réponses plus haut
- git --global config [Link] ”mon nom”
non, ”--global” est une option de la sous-commande config, pas de la commande git.
- git --global init [Link] ”mon nom”
deux fois non
- export GIT AUTHOR NAME=”mon nom”
c’est une autre manière de faire qui est prioritaire sur les paramètres des fichiers de configuration
Question 3
une seule réponse possible
Je ne renseigne pas mon nom et mon email dans la configuration de Git.
- vrai : si je fais une bêtise, les autres développeurs ne pourront pas me retrouver
no comment
- faux : ainsi les autres développeurs sauront sur quelles parties je suis intervenu
Question 4
plusieurs réponses possibles
Je veux enregistrer un répertoire vide dans Git. Je mets dans le répertoire le fichier suivant :
- .gitkeep vide
toutes les réponses fonctionnent, mais celle-ci est la plus communément utilisée.
- .gitkeep avec un espace dedans
- .gitignore vide
l’avantage est que ce fichier a un réel sens dans Git
- .empty vide
- .vide vide
Question 5
une seule réponse possible
Les fichiers .gitignore sont inutiles, autant sauvegarder un maximum d’informations dans les repositories
Git.
- vrai
- faux
Des informations inutiles perturberaient les autres développeurs et génèreraient des versions inutiles.
En général les fichiers générés automatiquement (compilation, cache) ne sont pas stockés dans les
repositories, ainsi que les données personnelles (configuration d’une IDE) ou sensibles (mot de passe)
du développeur.

9.3 Réponses quiz : Gestion des versions

cf. section 4.4, page 19


Question 1
une seule réponse possible
Git est un gestionnaire centralisé avec un dépôt principal et des dépôts secondaires.

G. Subrenat - 04/2021 - 63/70 Dépt Informatique - Université de Poitiers


9.3 Réponses quiz : Gestion des versions 9 RÉPONSES AUX QUIZ

- vrai
- faux
Git est bien décentralisé ce qui le rend à la fois complexe et puissant, mais nous n’étudierons pas
cet aspect.
Question 2
plusieurs réponses possibles
La commande “git status” ?
- elle affiche le copyright du logiciel Git
- elle indique les changements effectués depuis la dernière version enregistrée
- elle indique les fichiers qui seront intégrés à la nouvelle version et ceux qui ne le seront pas
- elle indique si le projet est public ou privé et les coordonées du propriétaire
Question 3
plusieurs réponses possibles
Pourquoi la commande “git commit” crée une nouvelle version en local et ne la propage pas directement
sur le repository distant ?
- Il n’existe pas obligatoirement un repository distant.
- Le système étant décentralisé, c’est au développeur de choisir sur quels dépôts distants il désire
propager la nouvelle version.
- Le développeur peut ainsi annuler des commit, ce qui ne sera plus possible une fois la version
transmise.
À utiliser avec circonspection ! Par exemple on supprime son dépôt local 49 et en refaisant un “git
clone” afin d’oublier les dernières versions locales. Autre exemple, on utilise la commande “git
commit --amend”. Il est bon de répéter que c’est à éviter au maximum.
- Le développeur n’a pas obligatoirement accès à internet.
Question 4
plusieurs réponses possibles
Pourquoi la commande “git add” est nécessaire et pourquoi tous les fichiers créés ou modifiés ne sont pas
directement intégrés à une nouvelle version ?
- Cela réduit le trafic réseau.
Pour une nouvelle version, on choisit les fichiers selon des critères d’utilité et non de taille.
- Cela réduit la place occupée sur disque.
idem
- Cela permet au développeur d’avoir une double validation avant de créer la version.
Il se trouve que c’est une conséquence, mais ce n’est pas la raison.
- Des informations inutiles perturberaient les autres développeurs et génèreraient des versions inutiles.
En général les fichiers générés automatiquement (compilation, cache) ne sont pas stockés dans les
repositories, ainsi que les données personnelles (configuration d’une IDE) ou sensibles (mot de passe)
du développeur.
Question 5
une seule réponse possible
Les SHA-1 pour identifier les versions sont trop risqués car il y a des risques de conflits (i.e. que deux
versions aient le même identifiant).
- vrai
Le terme “trop risqué” n’est pas correct. Il y a théoriquement un risque mais il tellement faible
qu’on le considère comme nul.
- faux
Question 6
une seule réponse possible
On peut identifier une version par autre chose qu’un SHA-1.
- vrai
On peut apposer un (ou plusieurs) tag à une version particulière. Notons aussi l’identifiant particu-
49. À ne faire que si il existe un dépôt distant !

G. Subrenat - 04/2021 - 64/70 Dépt Informatique - Université de Poitiers


9.4 Réponses quiz : Fonctionnement détaillé des versions 9 RÉPONSES AUX QUIZ

lier qu’est le nom d’une branche (master par exemple) et qui permet d’identifier la version la plus
récente de la branche.
- faux
Question 7
plusieurs réponses possibles
La commande “git checkout” permet de :
- naviguer dans l’historique des versions d’une branche
- changer la branche active
- supprimer physiquement une version devenue inutile
C’est impossible de supprimer physiquement une version : c’est l’essence de Git de garder une trace
de tous les états et de pouvoir revenir dessus.
- créer une nouvelle branche
Oui c’est possible avec l’option “-b” de checkout même si ce n’est pas la fonction première de cette
commande.
Question 8
une seule réponse possible
On peut modifier une version ancienne et faire des commit ?
- vrai
Mais à condition de créer une branche pour éviter les versions orphelines.
- faux
Réponse incorrecte (cf. ci-dessus) mais acceptée au vu des connaissances acquises jusqu’à présent.

9.4 Réponses quiz : Fonctionnement détaillé des versions

cf. section 5.5, page 25


Question 1
une seule réponse possible
On peut changer le SHA-1 d’une version (ou commit) afin par exemple d’avoir une numérotation plus
logique.
- vrai
- faux
On pourrait augmenter le risque d’avoir des collisions (dans le cas de projet à plusieurs milliers de
commit). En outre les SHA-1 sont certainement utilisés en interne : chaı̂nage des versions, position
de HEAD, ...
Question 2
une seule réponse possible
Détruire une branche supprime définitivement toutes les versions qui y sont rattachées.
- vrai
- faux
Ce n’est pas possible de supprimer définitivement des données par définition d’un outil de ver-
sionnement. En revanche, en supprimant une branche, on peut rendre des commit orphelins et
quasi-inaccessibles et de fait ils sont virtuellement supprimés.
Question 3
une seule réponse possible
Un pointeur de branche (comme master) désigne toujours le même commit, sinon on risquerait de perdre
des données.
- vrai
- faux
Au contraire, un pointeur de branche bouge sans arrêt en pointant systématiquement sur le commit
le plus récent.
Question 4
une seule réponse possible

G. Subrenat - 04/2021 - 65/70 Dépt Informatique - Université de Poitiers


9.5 Réponses quiz : Branches 9 RÉPONSES AUX QUIZ

Le pointeur HEAD, comme son nom l’indique, désigne toujours le premier commit d’une branche.
- vrai
- faux
Le premier commit est la racine de l’arbre et donc désigne toutes les branches du projet : avoir un
pointeur dessus n’a pas beaucoup d’intérêt. HEAD pointe sur le commit de travail courant qui est
potentiellement n’importe quel commit.
Question 5
une seule réponse possible
Sur une branche le chaı̂nage des commit est à l’envers : le premier commit de la liste chaı̂née est le dernier
à avoir été créé.
- vrai
C’est bien le cas. À terme nous manipulerons des arbres et, avec un chaı̂nage “à l’envers”, chaque
noeud n’a qu’un seul suivant (qui est donc le précédent dans l’ordre chronologique). En outre ce
sont les feuilles de l’arbre qui nous intéressent et donc avoir un accès direct dessus est intéressant ;
en revanche il faut avoir autant de pointeurs qu’il y a de feuilles.
- faux
Question 6
une seule réponse possible
HEAD peut être un pointeur sur un pointeur, mais ça n’a pas de sens.
- vrai
- faux
En l’occurrence c’est un point clé de Git, c’est ainsi que le pointeur de branche et HEAD peuvent
se déplacer en ensemble.
Question 7
une seule réponse possible
Une mauvaise utilisation du pointeur HEAD peut conduire à un état incohérent du repository.
- vrai
Et c’est même assez facile, soit en créant de nouveaux commit à partir de commit intermédiaires,
soit en positionnant mal le pointeur HEAD lorsqu’on le remet sur la dernière version d’une branche.
- faux

9.5 Réponses quiz : Branches

cf. section 6.6, page 38


Question 1
une seule réponse possible
Les branches sont très complexes à utiliser et sont de fait rarement utilisées.
- vrai
- faux
Les branches sont massivement utilisées. Outre les branches dédiées aux versions de production et
développement, l’ajout d’une fonctionnalité ou la résolution d’un ticket a généralement sa propre
branche.
Question 2
une seule réponse possible
Quelle commande permet de créer une branche ?
- git add branch ...
- git branch add ...
- git create branch ...
- git branch create ...
- git branch --create ...
- git branch ...
en précisant le nom de la branche

G. Subrenat - 04/2021 - 66/70 Dépt Informatique - Université de Poitiers


9.5 Réponses quiz : Branches 9 RÉPONSES AUX QUIZ

Question 3
une seule réponse possible
Quelle commande permet de changer la branche courante ?
- git branch --change ...
- git branch --checkout ...
- git checkout ...
Cette commande permet de se déplacer dans l’arbre en précisant un nom de branche, un sha1 ou
un tag.
- git checkout --branch ...
Question 4
une seule réponse possible
On peut créer une nouvelle branche uniquement à partir du commit le plus récent d’une branche existante ?
- vrai
- faux
On peut créer une branche à partir de n’importe quel commit (y compris le tout premier) ; il faut
cependant réfléchir à l’utilité de faire partir une branche d’un commit passé.
Question 5
plusieurs réponses possibles
Sachant qu’une branche est identifiée par une étiquette/pointeur sur son commit le plus récent, supprimer
ce pointeur est catastrophique.
- oui
Si la branche n’est pas encore fusionnée, supprimer l’étiquette rend tous les commit non visibles
(orphelins).
- oui mais non
Toujours dans le cas où la branche n’est pas fusionnée, il est malgré tout possible de récupérer les
commit orphelins avec la commande fsck.
- non
Si la branche est fusionnée à une autre, il n’y pas de conséquence à supprimer l’étiquette, si ce
n’est de perdre un nom indiquant le contenu de la branche ; et supprimer l’étiquette permet de la
réutiliser pour une autre branche.
Question 6
une seule réponse possible
Pour supprimer le dernier commit d’une branche, il suffit de reculer l’étiquette portant le nom de la
branche d’un cran.
- vrai
Même si c’est techniquement faisable, la réponse est refusée : c’est pervertir la notion de branche.
- faux
On part du principe que ce n’est pas possible (cf. l’autre réponse). En revanche il est possible de
faire un commit qui annule le dernier, ou plutôt ramène à l’avant dernier (commande revert).
Question 7
une seule réponse possible
Supprimer une branche permet de libérer de la place disque ?
- vrai
- faux
Les commit de la branche deviennent orphelins mais en aucun cas ne sont effacés du disque. Il n’est
pas possible de supprimer des commit 50 .
Question 8
une seule réponse possible
Lors d’une fusion, Git arrive souvent à rassembler les codes des deux branches de manière autonome ?
- vrai
il faut que ce soit la même partie d’un fichier qui soit modifiée pour que la charge de la fusion
50. À moins de modifier le répertoire .git à la main, ce qui est interdit et considéré comme une faute lourde dans une
entreprise.

G. Subrenat - 04/2021 - 67/70 Dépt Informatique - Université de Poitiers


9.6 Réponses quiz : Repositories distants 9 RÉPONSES AUX QUIZ

incombe au développeur.
- faux
Question 9
une seule réponse possible
On peut fusionner 3 branches ou plus simultanément ?
- vrai
mais on peut se demander si la fusion de deux branches n’est pas déjà suffisament complexe.
- faux
Question 10
plusieurs réponses possibles
Dans une fusion, à quelle branche rajoute-t-on un commit ?
- la branche courante
- la branche distante
la branche distante n’est pas modifiée.
- aucune
dans le cas du “fast forward”
Question 11
une seule réponse possible
En cas de conflit, le développeur doit choisir une des deux branches et éliminer l’autre ?
- vrai
c’est bien entendu une possibilité, mais il peut également faire un mixte des deux ou encore faire
un code complètement différent.
- faux
Question 12
une seule réponse possible
La commande “git stash” permet de :
- supprimer les modifications apportées depuis le dernier commit
- sauvegarder les modifications apportées depuis le dernier commit et revenir à la situation de celui-ci.

9.6 Réponses quiz : Repositories distants

cf. section 7.8, page 59


Question 1
une seule réponse possible
Pour récupérer un projet hébergé par une plate-forme, il faut avoir un compte sur cette dernière ?
- vrai
- faux
Si le projet est public, il est possible de le récupérer par le protocole https sans authentification.
Question 2
une seule réponse possible
La commande clone est la seule manière de créer un projet ?
- vrai
- faux
- la question n’a pas de sens
La commande “git clone” ne permet pas de créer un projet, mais d’avoir une copie locale d’un
projet existant. C’est la commande “git init” qui permet de créer un projet.
Question 3
plusieurs réponses possibles
Quelles commandes peuvent donner des informations sur un projet sans le modifier ?
- init
création d’un projet

G. Subrenat - 04/2021 - 68/70 Dépt Informatique - Université de Poitiers


9.6 Réponses quiz : Repositories distants 9 RÉPONSES AUX QUIZ

- clone
copie d’un projet en local
- status
elle sert uniquement à donner des informations sur les modifications en cours et non enregistrées
par un commit
- log
elle sert uniquement à donner des informations sur les différents commit
- push
modifie le repository distant
- pull
met à jour le repository local
- config
peut donner des informations ou modifier la configuration
- branch
peut donner des informations sur les branches ou les modifier
- fetch
met à jour le repository local
- merge
fusionne deux (ou plus) branches
Question 4
une seule réponse possible
Git est un modèle centralisé reposant sur un dépôt distant principal ?
- vrai
- faux
L’utilisation d’un repository centralisé et la plus commune, mais Git est prévu pour utiliser plusieurs
dépôts.
Question 5
une seule réponse possible
Du point de vue d’un développeur, en général une branche est gérée en combien d’exemplaires ?
- 1
- 2
- 3
la version locale, la version distancielle et la copie de la version distancielle en local.
- 4
Question 6
plusieurs réponses possibles
Quelle(s) commande(s) permet(tent) de lister les branches locales ?
- git branch
c’est le comportement par défaut
- git branch -r
ne liste que les branches distantes
- git branch --verbose
comme la première réponse avec plus d’information sur chaque branche
- git branch --list
liste également les branches distantes, mais les branches locales sont bien listées
Question 7
plusieurs réponses possibles
Quelle(s) commande(s) permet(tent) de lister les branches distantes ?
- git branch
cf. réponse précédente
- git branch -r
cf. réponse précédente
- git branch --verbose
cf. réponse précédente

G. Subrenat - 04/2021 - 69/70 Dépt Informatique - Université de Poitiers


9.6 Réponses quiz : Repositories distants 9 RÉPONSES AUX QUIZ

- git branch --list


cf. réponse précédente
Question 8
une seule réponse possible
Un tag ressemble à une branche si ce n’est qu’il ne peut pas bouger (on ne peut pas faire de commit
dessus) ?
- vrai
un tag est une étiquette permettant de référencer un commit avec un nom plus explicite que son
sha1.
- faux
Question 9
une seule réponse possible
Créer une branche dans le repository local la crée automatiquement dans le repository distant ?
- vrai
- faux
une branche locale peut exister sans son équivalent en distant, il faut une commande spécifique
pour créer la branche distante correspondante.
Question 10
une seule réponse possible
Supprimer une branche dans le repository distant la supprime automatiquement dans le repository local ?
- vrai
- faux
Les deux branches sont liées mais avec une certaine autonomie. Il est d’ailleurs possible d’avoir une
branche locale sans son équivalent dans le repository distant.
Pour supprimer complètement une branche, il faut explicitement supprimer sa version distante ainsi
que sa version locale.

G. Subrenat - 04/2021 - 70/70 Dépt Informatique - Université de Poitiers

Vous aimerez peut-être aussi