git permet de faire du contrôle de version. La différence avec d'autres systèmes de gestion de version est son aspect distribué et son système de branche.
La première partie de ce document ressemble beaucoup à l'introduction à git
que vous avez normalement eu en APL. Vous pouvez la relire très rapidement. De manière
générale, le site officiel est
une excellente source d'information.
La seconde partie contient plus de détails et des exercices pour aller plus loin, en
particulier, comment à travailler à plusieurs et une introduction aux branches, qui est
un aspect majeur de git
.
Tout au long de ce TP, je vous invite à conserver une petite feuille de papier ou un
fichier texte dans lequel prendre des notes pour lister chaque commande de
git
et une description indiquant à quoi elle sert.
À la fin de ce TP vous avez un quizz et une fin cocasse pour vous motiver à aller jusqu'au bout.
Notez que si vous travaillez seul, et si vous souhaitez juste synchroniser des
arborescences il existe la commande rsync
.
Du temps ancestral d'avant dropbox et autre client de nuage, pour travailler seul sans
home sur un serveur mais sur plusieurs machines, il existait rsync
, une
commande qui permet de synchroniser une arborescence manuellement ou régulièrement et
automatiquement avec un démon.
Il s'agit de «green IT» avant l'heure puisque rsync
ne va pas
transmettre intégralement la nouvelle version de l'arborescence mais va envoyer en gros
seulement les petites différences de chaque fichier.
Inconvénient par rapport à git
: on ne peut pas revenir à une version
antérieure. Avantage par rapport à git
: potentiellement beaucoup moins
gourmand en bande passante.
Pour rappel, nous avons un serveur git au département.
Rendez-vous sur la page d'accueil de Gitea et identifiez-vous. NB : ce service acceptera les mêmes identifiants que les machines virtuelles proxmox.
Pour éviter de saisir votre identifiant et votre mot de passe à chaque fois que vous transmettez une commande au serveur, je vous invite à suivre les étapes ci-dessous, si ce n'est pas déjà fait.
Une fois identifié, accédez aux paramètres de votre compte et mettez à jour le nom
complet et l'adresse e-mail principale. Nous allons nous assurer que git
sur
votre machine et Gitea sur le serveur ont bien les mêmes informations. Dans un terminal,
lancez les commandes suivantes (en utilisant les mêmes informations que sur
Gitea) :
git config --global user.name "Votre nom" git config --global user.email "login@domaine.example" git config --global core.editor vim
NB : si vous voulez utiliser un autre éditeur, vous pouvez tout à fait remplacer
vim
par emacs
ci-dessus. (trivia voir
editor war). C'est
l'éditeur qui sera choisi en cas de besoin par git
, par exemple si vous
faites un commit sans donner l'option -m "un message", git
vous demandera d'éditer le message en lançant un éditeur. Il vaut mieux donc choisir un
éditeur que vous maîtrisez un minimum.
Pour sécuriser les échanges entre votre machine et le serveur, il va vous falloir une paire de clés de cryptage. Tapez la commande suivante et validez sans entrer de réponse si des questions vous sont posées :
ssh-keygen -t rsa -C "login@domaine.example"
Ceci a créé parmi vos fichiers une clé privée et une clé publique. Nous devons maintenant donner la clé publique à Gitea. Commençons par afficher la clé publique :
cat .ssh/id_rsa.pub
Vous pouvez copier cette clé en la sélectionnant à la souris (aucun raccourci clavier n'est nécessaire). Revenez ensuite dans le navigateur et parmi les paramètres de votre compte Gitea, choisissez Clés SSH. Cliquez sur Ajouter une Clé puis copiez la clé dans la boîte Contenu (en appuyant sur la molette de la souris). Choisissez le nom que vous voulez pour la clé (vous pouvez par exemple l'appeler TP si c'est la clé générée dans une machine des salles de TP).
Chaque projet auquel vous participez doit avoir un dépôt dédié (et même plusieurs, comme nous le verrons par la suite). Vous pouvez aussi avoir un dépôt dédié pour chaque cours, surtout si il y a des TPs.
Créez un nouveau dépôt en utilisant le bouton qui ressemble à un +.
Si c'est un projet, il faut probablement suivre une convention de nommage pour que le correcteur retrouve le projet facilement. Rendez-le privé. Donnez les accès adaptés au(x) correcteur(s) et autre(s) membre(s) de votre projet.
Dans la catégorie .gitignore vous pouvez choisir plusieurs modèles en fonction de votre projet et du type de fichiers qu'il va contenir (ou plus exactement de ceux que vous ne souhaitez pas sauvegarder).
Vous pouvez ensuite valider et constater que vous avez un dépôt contenant deux fichiers
Le dépôt en ligne est prêt et vous n'avez plus vraiment besoin d'accéder à Gitea par son interface web à partir de maintenant.
Pour cloner un dépôt localement sur votre machine, il vous suffit de regarder son adresse
sur un serveur git
et d'y avoir accès.
Par exemple, pour le dépôt du projet PouetPouet de l'utilisateur toto
sur le serveur git
de l'IUT, il faut saisir :
git clone gitea@dwarves.iut-fbleau.fr:toto/PouetPouet.git
S'il s'agit de votre dépôt que vous venez de créer, vous allez voir si vous regardez tous
les fichiers y compris les fichiers cachés (par exemple en faisant ls
-a
) :
.git
.gitignore
README.md
Le dépôt local à proprement parler est dans le répertoire .git
. Vous n'avez
pas besoin de le visiter, mais vous pouvez y jeter un coup d'oeil si vous êtes curieux.
Le répertoire PouetPouet
est le répertoire de la copie de travail
des fichiers du dépôt.
Attention il faut éviter de cloner un dépôt
git
dans un dépôt git
. C'est possible de le faire, mais c'est
un mécanisme
avancé de git.
Alternativement, vous pouvez utiliser git init
pour créer un dépôt local.
Ensuite il faut utiliser git add
et git commit
pour indexer des
fichiers puis faire un point de sauvegarde local (comme expliqué ci-dessus).
Ensuite git remote add origin
suivi de l'url du dépôt sur le serveur
(NB : origin est le nom que git
donne au dépôt du serveur
distant par défaut ; il est parfois possible d'avoir plusieurs dépôts distants)
pour indiquer le nom du dépôt distant.
Finalement il faut faire git push -u -f origin master
(NB :
master est le nom de la branche principale, ici celle du dépôt local, l'option
-u va éviter d'avoir à répéter origin et master par la suite
dans les commandes).
Dans cette partie nous illustrons l'usage de git
à travers quelques exemples
et exercices.
L'utilisation de base pour un travail seul en local avec git
sans sauvegarde
distante est la suivante :
monFichier
git add
)
git commit
)
Par exemple :
emacs monFichier git add monFichier git commit -m "un message court expliquant le changement de monFichier"
Si vous travaillez seulement en local, ceci suffit à avoir un système de version permettant de revenir en arrière.
Pour revenir en arrière sur 1 fichier il faut utiliser :
git restore --source <le numéro de version> monFichier
(NB : c'est l'analogue d'un rollback de base de données)
Pour connaître le numéro d'une version, vous pouvez utiliser git log
.
Si vous êtes un peu perdu git status
donne beaucoup d'information et suggère
des commandes. Vous pouvez lire le man
sur ces commandes ou regarder les
docs en ligne.
Remarque git restore
est
relativement récent et avant il y avait git checkout
. Cette seconde commande
a beaucoup d'usages, ce qui contrevient à l'esprit unix une commande pour un usage. Sauf
si vous maîtrisez bien git checkout
, mieux vaut utiliser les diverses
nouvelles commandes qui la remplacent, comme git restore
et git
switch
.
Exercice 1. Dans un nouveau dépôt local git
, créez un
nouveau fichier git.md
et inserez-y le contenu ci-dessous :
Git is a term of insult denoting an unpleasant, silly, incompetent, annoying, senile, elderly or childish person. As a mild oath it is roughly on a par with prat and marginally less pejorative than berk. Typically a good-natured admonition with a strong implication of familiarity, git is more severe than twit or idiot but less severe than wanker, arsehole or twat when offence is intended.
Sauvez le fichier. Lancez la commande git status
. Indexez le nouveau
fichier, puis créez un point de sauvegarde avec le message "git definition".
Lancez la commance git log
.
En cette période de jubilé de platine de sa majesté, il est difficile de laisser visible un tel texte. Nous allons maintenant chiffrer le contenu du fichier en ROT13, avec la commande :
sed -i 'y/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM/' git.md
Ensuite refaites un nouveau point de sauvegarde avec le message "vg qrsvavgvba".
Le jubilé étant passé et Bojo étant toujours premier ministre, on décide de revenir à la
version antérieure. Restorez le contenu du fichier git.md
.
Avec un serveur distant, vous pouvez normalement garantir de conserver tout votre travail
qui est sauvé sur le serveur git
, même si votre ordinateur personnel vous
lâche.
Si vous avez plusieurs machines/comptes, il faut faire un git pull
pour
récupérer la version du serveur.
Ensuite vous travaillez en local comme ci-dessus (cycle édition, git add
,
git commit
).
Dès que vous voulez sauver sur le serveur, il faut faire un git push
.
Remarque Vous n'êtes pas obligé de faire un push pour chaque commit local. Le commit local sert à faire des undo alors que le push sert à montrer des changements relativement conséquents (potentiellement utile pour d'autres lecteurs que vous le jour où vous travaillez à plusieurs). Voir cette question pour plus de détails.
Exercice 2. On reprend l'exercice précadent avec un fichier
git2.md
contenant 2 lignes de plus que précédemment.
Git is a term of insult denoting an unpleasant, silly, incompetent, annoying, senile, elderly or childish person. As a mild oath it is roughly on a par with prat and marginally less pejorative than berk. Typically a good-natured admonition with a strong implication of familiarity, git is more severe than twit or idiot but less severe than wanker, arsehole or twat when offence is intended. The term is used by Graham Chapman in the Monty Python sketch "Argument Clinic". The term is also frequently used by the character Derek 'Del Boy' Trotter in TV series Only Fools and Horses.
Indexer le fichier, sauver le fichier, faire un commit local. Faire du ROT13, indexer, sauver le fichier, faire un commit local.
Faire un push, lancer git log
en local, aller voir les révisions sur
l'interface web de Gitea.
Faire un restore
en local. Regarder si il y a des effets sur le dépôt local.
Regarder si il y a des effets sur le dépôt distant via l'interace web.
Le jubilé étant passé et Bojo étant toujours premier ministre, on décide de revenir à la
version antérieure. Restorez le contenu du fichier git.md
.
Vous n'êtes pas obligé de travailler à deux pour cet exercice, ni même d'avoir deux machines clientes. Vous pouvez simuler la seconde personne en vous mettant dans un autre répertoire sur votre machine et en y clonant le dépôt.
Dans cet exercice nous simulons un conflit de version sur un fichier. En gros vous faites
un git push
et le message vous indique qu'il y a un conflit et comment le
résoudre. Il faut faire un git pull
. Git essaye de faire la fusion
automatique et vous indique un conflit. Vous devez éditer le fichier qui contient
maintenant très clairement les lignes divergentes de l'autre version. Vous faites votre
selection, sauvez le fichier, l'indexer, commit puis pousser le changement.
Normalement ceci fonctionne assez bien pour des choses simples, en particulier si vous changez des lignes différentes d'un fichier.
Exercice 3. Ajouter à votre dépôt local les fichiers du
précédent TP noté
Memoire.java
et MaMemoire.java
.
Les indexer, faire un commit, pousser sur origin. Donner accès en écriture au dépôt distant à un collègue.
En parallèle sur vos machines respectives :
Puis dans cet ordre :
git pull
.
MaMemoire.java
pour avoir une version cohérente du
fichier appliquant les changements des 2 personnes.
git add
, un git commit
puis un git
push
.
git pull
.
L'étape d'édition est probablement inutile si vous avez changé des lignes différentes du fichier.
Exercice 4. Reprendre l'exo précédent, mais cette fois ajoutez chacun des changements sur des lignes communes. Par exemple vous changez chacun la javadoc de la même méthode ou bien vous changez le nom de la même variable dans la même méthode. Normalement la résolution automatique du conflit et la fusion des fichiers va échouer et vous allez être obligé de faire la fusion manuelle.
La spécificité de git
par rapport à d'autres système de contrôle de versions
est que git
encourage très fortement l'utilisation très fréquente de
branches et que sous le capot il s'agit de quelque chose d'assez léger.
Pour fabriquer une branche, on va faire :
git branch LeNomDeMaBranche
Pour changer de branche, on peut utiliser git checkout
mais je vous
recommande la commande plus moderne qui ne sert qu'à changer de branche qui s'appelle
git switch
. Par exemple, pour basculer sur cette branche qu'on vient de
créer, on va faire :
git switch LeNomDeMaBranche
Notez que vous aviez avant d'ajouter cette nouvelle branche une branche par défaut qui se nomme master.
Dans la suite je vais supposer que chaque branche est dans un état propre, à savoir tous
les fichiers utiles ou changés sont indexés (git add
) et il y a un point de
sauvegarde local (git commit
). Ceci permet de ne jamais perdre son travail
quand on bascule de branche en branche.
Vous pouvez changer à tout moment de branche avec git switch
.
Pour fusionner le travail d'une branche dans une autre branche, il faut vous placer dans
la branche dans laquelle vous souhaiter injecter le changement et utiliser git
merge
. Par exemple, pour insérer les changements de LeNomDeMaBranche dans
master il faut juste faire :
git switch master git merge LeNomDeMaBranche
Si LeNomDeMaBranche est juste un successeur de master la fusion est
très simple pour git
puisque c'est juste du déplacement de pointeur (en gros
master va pointer sur LeNomDeMaBranche). Dans son jargon,
git
évoquera un fast-forward. Si au contraire
LeNomDeMaBranche et master ont un ancêtre commun car il y a eu des
changements dans la branche principale master depuis que la branche
LeNomDeMaBranche a poussé, alors la fusion est un peu plus compliquée à mettre
en oeuvre, mais pourra probablement être faite automatiquement. Dans son jargon,
git
évoquera un three-way merge. Si git
n'arrive pas à
résoudre tout automatiquement, alors il va évoquer un merge conflict. Vous
pouvez utiliser git status
, puis changer à la main ce qu'il faut.
Si vous avez intégré le travail d'une branche qui ne sert maintenant plus à rien, vous pouvez l'effacer en faisant :
git branch -d LeNomDeMaBranche
Attention Ce n'est pas quelque chose qu'on peut annuler.
Le livre en ligne sur le site de git (disponible en plusieurs langues dont le français) est très bien fait et vous pouvez avoir plus de détails en regardant ici et là.
Jeu en javascript pour s'entraîner
git
?
git
sont-ils indexés ?
git
centralisé ?
git
?
git
?