Cette page est dédiée à donner quelques pistes concernant
l'utilisation de Git, un logiciel de
gestion de version, à l'intérieur des projets de 1ère année à
l'ENSEIRB.
Les projets se font par équipes, mais les principes décrits dans ces pages doivent être compris par chacun. A la fin de cette feuille, chaque membre de l'équipe doit avoir :
Les projets se font par équipes, mais les principes décrits dans ces pages doivent être compris par chacun. A la fin de cette feuille, chaque membre de l'équipe doit avoir :
- créé un répertoire de travail personnel contenant les sources de son projet;
- communiqué une révision dans un des fichiers de sources à l'intérieur du projet.
Principes généraux
Lorsque l'on réalise un projet basé sur un ensemble de fichiers
source, qu'il s'agisse du code d'un programme en
langage
Une version du projet, appelée aussi révision, représente l'ensemble des fichiers appartenant au projet à un moment fixé de son développement, telle une photographie de son état instantané. Une suite de révisions consécutives est appelée une branche. Le projet évolue en suivant un ensemble de branches, à partir de sa révision initiale vers une révision propre à sa mise en production.
Lorsque l'on commence à travailler à plusieurs, chaque membre de l'équipe dispose de sa propre révision, et il n'est pas évident de pouvoir partager ses révisions entre les personnes.
Pour apporter une solution à ces problèmes, on adopte le système suivant :
Le diagramme suivant décrit les étapes principales de la vie d'un dépôt (les blocs sont cliquables) :
C
ou du source d'un rapport rédigé
en LaTeX
, on passe inévitablement par de nombreuses
versions successives.
Une version du projet, appelée aussi révision, représente l'ensemble des fichiers appartenant au projet à un moment fixé de son développement, telle une photographie de son état instantané. Une suite de révisions consécutives est appelée une branche. Le projet évolue en suivant un ensemble de branches, à partir de sa révision initiale vers une révision propre à sa mise en production.
Lorsque l'on commence à travailler à plusieurs, chaque membre de l'équipe dispose de sa propre révision, et il n'est pas évident de pouvoir partager ses révisions entre les personnes.
Pour apporter une solution à ces problèmes, on adopte le système suivant :
- Les sources du code sont placées dans un endroit particulier appelé dépôt, capable de stocker toutes les révisions du code. Dans le cadre des projets, il vous est fourni un dépôt placé sur la forge de l'ENSEIRB qui sert de référentiel sur l'état d'avancement du projet (par défaut, il s'appelle origin)
- Chaque membre du projet travaille sur les sources qu'à l'intérieur d'un dépôt local, situé dans un répertoire de son arborescence de fichiers. Il n'y a pas de différence de nature entre le dépôt local et le dépôt sur la forge.
Le diagramme suivant décrit les étapes principales de la vie d'un dépôt (les blocs sont cliquables) :
Créer un dépôt local
Cette section est à réaliser par chaque membre de l'équipe.
- Connectez-vous sur
la forge de
l'ENSEIRB, et
rendez-vous sur la page dédiée à votre projet, et suivez plus
précisément l'onglet nommé "Dépôt" ou "Repository".
Cette page contient une commande de la forme
suivante :
git clone https://<user>@thor.enseirb-matmeca.fr/git/chabadabada
Il va sans dire qu'il n'existe pas de dépôt nomméchabadabada
, et qu'il faut remplacer la partie<user>
, ce qui implique que copier/coller directement la commande précédente est un acte inutile. - Visualisez le contenu du dépôt sur l'accès
web en suivant le
lien https://thor.enseirb-matmeca.fr/web/git/gitweb.cgi?p=chabadabada. Vous
devez normalement constater qu'il est vide.
Un très bon logiciel pour visualiser l'état local de son dépôt est installé sur les machines de l'ENSEIRB avec pour nom
gitg
. - Placez vous dans un terminal, et déplacez vous dans un
répertoire dans lequel vous comptez mettre les sources de vos
projets. Ensuite, recopier la commande précédente dans le
terminal et l'exécuter. Si tout se passe correctement, le
résultat devrait être de l'une des des formes suivantes.
-
Si le dépôt que vous clonez est initialement vide :
Cloning into 'chabadabada'... warning: You appear to have cloned an empty repository.
-
Si le dépôt que vous clonez contient déjà des données :
remote: Counting objects: 72486, done. remote: Compressing objects: 100% (36856/36856), done. remote: Total 72486 (delta 35803), reused 70908 (delta 34681) Receiving objects: 100% (72486/72486), 226.64 MiB | 8.30 MiB/s, done. Resolving deltas: 100% (35803/35803), done.
chabadabada
dans le répertoire courant, contenant la dernière révision de la branche principale. Il est toujours possible de modifier le nom du répertoire de travail après coup, par exemple en le déplaçant. Initialement, ce répertoire contient un ensemble de fichiers sources déjà ajoutés au dépôt, ainsi qu'un sous-répertoire nommé.git/
servant à gérer le dépôt lui-même. -
Si le dépôt que vous clonez est initialement vide :
- Créer un fichier de configuration pour git. Les détails de la
configuration peuvent être omis dans un premier temps, et il est
possible de générer ce fichier à l'aide de la commande
suivante :
Dans un second temps, il sera possible pour les plus aventureux de revenir sur cette étape en lisant la section Configurer son usage de git
ssh ssh.enseirb-matmeca.fr /net/ens/renault/local/bin/init-gitconfig.sh > ~/.gitconfig
- Assurez vous que chaque membre de votre équipe ait bien créé un répertoire de travail personnel. C'est important pour la suite.
Composer du code dans le dépôt
Cette section est à réaliser par un seul
membre de l'équipe. Les autres peuvent regarder, ils auront à
refaire la même chose plus tard.
- Se positionner à l'intérieur de son répertoire de travail
(à l'intérieur de celui nommé
chabadabada
si vous n'avez pas changé son nom). Créer un fichier authors.txt vide.touch authors.txt
- Ajouter une ligne à l'intérieur du fichier contenant vos noms, prénoms et adresse mail.
Communiquer une révision
L'opération que nous allons décrire permet de valider un ensemble de
modifications dans le code pour créer une nouvelle révision, et est
communément appelé un commit en anglais. Dans
cet exemple, nous allons supposer que cette modification porte sur
un unique fichier
authors.txt
.
-
Visualiser l'état des fichiers dans le dépôt avec la commande
suivante :
Si le fichier n'a jamais été communiqué au dépôt, le résultat devrait être de la forme :
git status
Si le fichier était déjà présent dans le dépôt, le résultat devrait être de la forme :Untracked files: (use "git add <file>..." to include in what will be committed) authors.txt
Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: authors.txt
-
Valider cette modification localement :
Cette commande indique que localement, les modifications du fichier
git add authors.txt
authors.txt
ont été ajoutées au répertoire de travail. La commandegit status
devrait maintenant indiquer :Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: authors.txt
En cas d'erreur sur l'ajout de la modification, il est toujours possible de revenir en arrière (comme indiqué par git) avec la commandegit reset HEAD authors.txt
. De plus, il reste toujours possible, sans faire dereset
, de continuer à modifierauthors.txt
et de faire un autregit add
plus tard, si l'on estime qu'il manque encore quelques finitions. - Valider la modification localement, en ajoutant un commentaire :
git commit
Normalement, cette commande ouvre un éditeur dans lequel écrire le commentaire. Il est possible de configurer cet éditeur en positionnant la variableUne fois la modification validée, une nouvelle révision a été créée.EDITOR
dans son environnement, par exempleexport EDITOR=emacs
. Le commentaire peut être passé directement en ligne de commande en passant l'option-m
à git. Il existe un ensemble de bonnes pratiques pour écrire des messages de commits, par exemple ici. - Comme il s'agit d'une modification des sources, il faut la
communiquer au dépôt distant. Le dépôt distant se nomme par
défaut origin, et la branche à
communiquer master. Communiquer votre
modification des sources avec la commande suivante :
git push origin master
- Constater que vos modifications sont bien apparues dans le
dépôt, en utilisant l'accès web et le
logiciel
gitg
.gitg
est un outil local. Les autres membres de l'équipe ne pourront visualiser les modifications surgitg
qu'après avoir récupéré la version la plus récente du dépôt.gitg
, il devrait être possible de distinguer les étiquettes de la branche locale (master
) et de la branche distante (origin/master
).
- La décomposition d'un développement en suite de révisions simple est une opération fondamentale en terme de développement logiciel. Il devient possible de valider plusieurs modifications successivement, en leur assignant des commentaires différents. En conséquence, retrouver des modifications après coup devient bien plus aisé.
- Les commentaires sont une source d'information importante pour comprendre la manière dont évoluent les sources. Ils doivent être à même d'expliquer précisément les modifications que vous venez de faire. Un commentaire vide est un acte improductif.
Récupérer la version la plus récente du dépôt
Lorsque l'on reprend son travail après une période d'absence ou plus
simplement avant de communiquer ses modifications locales à
distance, il est impératif de vérifier que
l'on est bien cohérent avec les modifications les plus récentes du
dépôt.
- Avant toute chose, vérifier l'état du dépôt en s'assurant qu'il n'y a pas de modifications locales.
- Synchroniser le dépôt local avec le dépôt distant, nommé origin :
-
Fusionner (en anglais, "to merge") les modifications distantes dans
votre dépôt local :
git merge origin/master
Normalement, la fusion s'est déroulée sans erreurs, ce que l'on peut voir grâce au mot cléUpdating 6ec514a..cab0f1b Fast-forward authors.txt | 1 + 1 file changed, 1 insertion(+)
Fast-forward
. Il est néanmoins possible que la fusion ne puisse être réglée simplement, auquel cas le message obtenu devrait être de la forme :Dans ce cas, il faut se rendre à la section Gérer un conflit.Auto-merging authors.txt CONFLICT (content): Merge conflict in authors.txt Automatic merge failed; fix conflicts and then commit the result.
git fetch origin
remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From /path/to/the/local/repository 6ec514a..cab0f1b master -> origin/master
L'utilisateur expérimenté de git réalisera les deux opérations
précédentes en une seule commande :
git pull origin
master
. Il est néanmoins important de noter qu'il est
toujours possible de décomposer cette action, pour visualiser les
modifications distances avant de les
fusionner avec son code.
Continuer à composer dans le dépôt
-
Pour simuler un développement à plusieurs sur le dépôt, chaque
membre de l'équipe peut ajouter son identité dans le
fichier
authors.txt
. - Une fois cela fait, les autres membres de l'équipe récupèrent la dernière version du dépôt et la fusionnent avec leur version locale.
Gérer un conflit
Du fait de la présence de multiples dépôts dans lesquels le code
peut être modifié, il est possible que la même
branche
Mettons que la dernière fusion/merge ait amené au résultat
suivant :
master
ait divergé entre deux dépôts
(typiquement avec la même branche sur un dépôt distant,
comme origin/master
). Dans ce cas, une fusion/merge
risque d'amener à un conflit. Il convient de
ne surtout pas paniquer, cela fait partie des tracas standards du
développement logiciel.
Auto-merging authors.txt CONFLICT (content): Merge conflict in authors.txt Automatic merge failed; fix conflicts and then commit the result.
git status
, qui devrait indiquer :
On branch master Your branch and 'origin/master' have diverged, and have 1 and 1 different commits each, respectively. (use "git pull" to merge the remote branch into yours) You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: authors.txt no changes added to commit (use "git add" and/or "git commit -a")
Il faut bien noter que l'opération de fusion/merge ne s'est pas
terminée ("no changes added to commit"). Git vous met dans un état
où il est possible de l'assister à terminer cette fusion
correctement.
Pour chaque fichier en conflit, appliquer la procédure
suivante :
-
Ouvrir le fichier dans un éditeur (dans notre
exemple
authors.txt
). -
Rechercher dans l'éditeur les blocs de la forme suivante :
Git a modifié de lui-même le fichier pour inclure, aux endroits qui lui semblaient différents, les deux versions. Il est facile de rechercher ces blocs car les marqueurs
<<<<<<< HEAD David, le programmeur extrémiste. ======= David, le programmeur de l'extrême. >>>>>>> origin/master
<<<<<<<
,=======
et>>>>>>>
ne sont quasiment jamais utilisés.- La zone délimitée
par
<<<<<<<
et=======
représente la version locale du code (branchemaster
). - La zone délimitée par
=======
et>>>>>>>
représente la version distante du code (brancheorigin/master
).
- La zone délimitée
par
- Modifier le code de manière à éliminer tous les marqueurs. Il est ainsi facile de choisir une version des deux versions à garder, ou de faire une sorte de mélange des deux si besoin.
-
A la fin des modifications, ajouter le code au commit (ici le
fichier en conflit)
git add authors.txt
-
Une fois tous les fichiers en conflit gérés, terminer la
fusion (un message de commit est généré automatiquement) :
git commit
Récupérer un état catastrophique
Il est toujours possible de se retrouver dans une situation dans
laquelle continuer à faire des commandes
git
est
difficile ou met en péril l'état du code source sur lequel on
travaille. Il peut s'agir en particulier :
- d'une situation où les commits sont rejetés par le serveur
(penser avant tout
à bien
configurer
git
, et ensuite tenter d'appliquer la procédure décrite ici avant) - d'une situation où du code est écrit dans le dépôt sans avoir
été committé, mais toute action faite avec
git
risquerait de perdre ce code (c'est normalement difficile, mais avec beaucoup de malchance et/ou de mauvaise volonté, on ne sait jamais)
chabadabada
.
Si vous en arrivez à cette appliquer cette procédure, c'est
normalement après avoir vérifié qu'il n'existait pas une méthode
moins grossière pour sauver votre travail de développement.
-
Se placer dans le répertoire parent du répertoire correspondant
à votre dépôt, et le renommer.
mv chabadabada chabadabada.old
-
Recréer une
version du dépôt local.
git clone https://<user>@thor.enseirb-matmeca.fr/git/chabadabada
-
Copier les données de l'ancien dépôt dans le dépôt nouvellement créé.
cp -R chabadabada.old/* chabadabada/
- Communiquer les modifications dans le dépôt distant.
cd chabadabada/ git commit -m -a "Récupération catastrophique" git push origin
chabadabada
contiendra la dernière version du code du dépot initial. Tous les
commits intermédiaires auront été perdus. Les fichiers supprimés du
dépôt entre temps devront être supprimés à nouveau. Si vous estimez
ne plus avoir besoin des vieux commits, vous pouvez après coup
supprimer le dépôt chabadabada.old
.
Renommer les auteurs de commits rejetés
Cette procédure permet de modifier les noms et emails d'utilisateurs
de certains commits. Dans le cas où ces commits sont rejetés par la
forge, elle permet de récupérer une situation mal engagée. Dans tous
les cas, commencez
par configurer votre
dépôt et n'appliquez cette procédure qu'après
avoir fait une copie dudit dépôt.
Commencez par compter combien et quels sont les commits fautifs :
Commencez par compter combien et quels sont les commits fautifs :
- Si il n'y en a qu'un seul, et que c’est le dernier, appliquer
la commande suivante :
Cela remplacer l'auteur du commit par celui défini dans la configuration.
git commit --amend --reset-author
-
Si il y en a plus d’un, ou ce n’est pas le dernier, alors
appliquer l'une des commandes suivantes depuis les machines de
l'école :
L'option
~fmorandat/bin/rewrite-author.sh --rename "Ancien Nom" --reemail "ancien@email.com"
--rename
permet de réécrire un nom en utilisant celui spécifié dans la configuration, et--reemail
de réécrire un email. Faire bien attention à ne pas réécrire les commits corrects (qu'ils vous appartiennent ou pas), ainsi que les commits déjà poussés sur la forge.
Modifier des commits passés
Cette procédure permet de modifier entièrement un ensemble de
commits n'ayant pas encore été poussés sur la forge. Dans le cas où
ces commits sont rejetés par la forge. Dans tous les cas, commencez
par configurer votre
dépôt et n'appliquez cette procédure qu'après
avoir fait une copie dudit dépôt.
Commencez par compter combien et quels sont les commits
fautifs :
- Si il n'y en a qu'un seul, et que c’est le dernier, préparez
une modification du code comme si c'était un nouveau commit (par
exemple en appliquant des
git rm
). Validez enfin le commit avec la commande suivante :Cela élimine le dernier commit et le remplace par un nouveau commit dans le nouvel état.git commit --amend
- Si il y a plusieurs commits, alors il va falloir les
reprendre un par un. Noter la révision du dernier commit
transmis à la forge, et appliquer la commande suivante :
Cette commande permet de rejouer l'ensemble des commits depuis la révision donnée en paramètre. Il suffit alors d'éditer les commits fautifs, et de les amender au fur et à mesure. La procédure est décrite dans le Git Book.
git rebase --interactive <revision>
Visualiser l'état du dépôt
La commande suivante permet de visualiser l'état du dépôt :
Selon l'état dans lequel se trouve le dépôt, il est possible
d'obtenir une somme d'informations comme :
Git est un logiciel assez prévenant, et il est donc possible de voir
ici 4 items (mis en évidence par les '•') :
git status
On branch master •Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) •Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: README.txt •Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: authors.txt •Untracked files: (use "git add <file>..." to include in what will be committed) liste_des_courses.txt
- Que le dépôt local n'a pas encore communiqué ses modifications au dépôt distant ("Your branch is ahead of 'origin/master' by 2 commits")
- Qu'un commit est en préparation, avec le
fichier
README.txt
, et qu'il ne demande qu'à être communiqué avec la commandegit commit
. - Qu'un fichier
authors.txt
a été modifié localement mais n'est pas inclus dans le commit précédent. - Qu'un fichier
liste_des_courses.txt
est à l'intérieur du dépôt local, mais n'est pour l'instant pas géré par git.
Configurer son usage de git
Il est possible de configurer un certain nombre de préférences pour
l'utilisation de tous ses dépôts git. Le fichier de configuration
est usuellement placé dans son répertoire personnel
comme
Le fichier
Il est parfaitement possible de modifier ce fichier dans un éditeur,
mais il est aussi possible de le faire à l'aide de la commande
suivante :
$HOME/.gitconfig
. En cas de perte de son fichier,
ou pour revenir à une configuration initiale, il suffit
d'appliquer :
ssh ssh.enseirb-matmeca.fr /net/ens/renault/local/bin/init-gitconfig.sh > ~/.gitconfig
.gitconfig
est un fichier texte de la forme
suivante :
[http] sslVerify = false [color] ui = auto
git config --global color.ui "auto"
Si la commande précédente ne comporte pas
le
Parmi les préférences que l'on peut définir dans ce fichier, il y en
a deux qui sont particulièrement importantes :
--global
, et qu'elle est effectuée depuis un dépôt
git, alors la configuration ne concernera que ce dépôt. user.name
, qui fixe le nom de l'utilisateur à associer aux commits,- et
user.email
, qui fixe son adresse email.
Tout dépôt GIT utilisé sur la forge de
l'ENSEIRB ne peut être utilisé qu'avec une
configuration correcte, à savoir un nom d'utilisateur valide et un
email propre à l'école. Toute utilisation du dépôt en dehors de
ces conditions d'utilisation pourra
être rejetée.
Ignorer la présence de fichiers dans le dépôt
Le fichier
.gitignore
à la racine du dépôt permet de
lister les fichiers que Git va ignorer, à savoir ceux qui
n'apparaîtront pas dans la section Untracked files
lors
des appels à la commande git status
.
- Ce fichier n'existe pas originellement dans le dépôt. Il faut donc le créer si le besoin d'ignorer des fichiers se fait sentir.
-
Il s'agit d'un fichier de script classique, les commentaires
sont les lignes commençant par un
#
, et chaque ligne peut contenir un nom de fichier relatif à la racine ou une expression régulière. - Il est versionné, comme les autres fichiers de code, ce qui permet de le faire évoluer au fur et à mesure du développement, et de communiquer ses modifications à des dépôts distants.
.gitignore
pour des projets
en C
:
# .gitignore -- List of files ignored by git *.[oa] *~
Pour aller plus loin ...
Il est bien évident que cette page passe sous silence un nombre de
détails gigantesques quant à ce logiciel tentaculaire qu'est git, et
c'est pourquoi il est possible de trouver d'autres sources de
documentations plus génériques et/ou plus avancées en se référant
à :
- Le livre Pro Git accessible en ligne, et qui dispose d'une version en français, rassemble la documentation de référence du langage de manière très lisible.
- Le site Git, the simple guide résume les commandes git de base de manière très synthétique, et a le bon goût de les rassembler dans une aide-mémoire allant à l'essentiel.
- A visual Git reference explique la plupart des opérations effectuées par git de manière visuelle. Il permet de se faire une idée assez concrète du fonctionnement interne de git.
- Learn Git Branching (déconseillé aux débutants), un site simulant les interactions avec un dépôt git dans un navigateur, et fournissant des exercices pour s'entraîner avec les concepts les plus complexes de l'outil.
- Un ensemble de slides écrits par E. Fleury, extrêmement complets et didactiques pour comprendre le fonctionnement de git.
- La foire aux questions du logiciel Git-Tower, qui, bien que faisant un peu de publicité à leurs produits, fournit des conseils clairs et détaillés.
- L'aide-mémoire proposé sur github est une autre liste de commandes plus complète que le précédent.