Un système de contrôle de versions (version control system VSC en anglais ou encore version control manager VCM ) est un outil permettant la gestion de différentes versions d’un code source informatique.
Les systèmes de contrôle de versions sont devenus des incontournables pour tous les projets de développement informatique. La diversité des systèmes existants sur le marché actuellement, montre bien l’importance d’avoir en permanence la dernière version fonctionnelle du code d’un projet. Ces systèmes permettent ainsi de:
- Centraliser et sauvegarder tout l’historique des modifications d’un projet
- Permettre aux différents utilisateurs de travailler sur des versions différentes du projet en question
- Naviguer entre toutes les versions du projet
Les systèmes de contrôle de version utilisent 2 principaux modèles:
- Le modèle centralisé
Avec ce modèle, tous les utilisateurs se connectent à un répertoire (‘repository’ en anglais) central.
- Le modèle distribué
Avec ce modèle, tous les utilisateurs disposent d’une copie de tout le répertoire partagé en local sur leurs ordinateurs.
Les trois systèmes les plus populaires sont: Git, Subversion et Mercurial. Git, sur lequel on va se focaliser, est un système utilisant le modèle distribué. Github quant-à-lui, est le service web hébergeant les projets Git.
Git et les différents terminologies associées
La compréhension et la maîtrise de Git passe par la bonne connaissance des différents mots-clés utilisés. On citera ci-dessous (liste non exhaustive) quelques mots-clés avec leurs significations respectives:
COMMIT
Git traite chacune de ses données comme un ensemble de clichés d’un système de fichiers. On peut imaginer chaque fichier comme étant enregistré sous forme d’images associées à un temps dans la vie du projet. La commande COMMIT permet ainsi la prise d’un instantané du code source à un moment donné en enregistrant également toutes les informations associées.
Repository \ Repo (ou répertoire)
Le ‘repository’ est tout simplement un dossier contenant les fichiers du projet ainsi que certains fichiers permettant la communication avec Git. Un répertoire peut exister localement sur l’ordinateur d’un utilisateur ou sous forme d’une copie locale d’un répertoire à distance.
Working directory (répertoire de travail)
Le répertoire de travail correspond au répertoire dans lequel un utilisateur travaille localement sur son ordinateur. Il diffère donc du répertoire créé par la commande COMMIT vu plus haut.
Staging area
L’aire d’attente correspond à un espace intermédiaire dans lequel sont rangés les fichiers qui seront sauvegardés dans la ‘repository’ une fois la commande COMMIT exécutée. Seuls les fichiers contenus dans l’aire d’attente seront synchronisés avec le répertoire central.
SHAI (Secure Hash Algorithm)
Chaque fois que la commande COMMIT est exécutée, des versions de fichiers passent de l’aire d’attente au répertoire central. Lors de cette opération, un identifiant est associé à la version de fichier fraîchement sauvegardée. SHAI correspond donc l’identifiant unique d’un COMMIT.
Branch (branche ou ramification)
Une branche correspond à une ligne de développement d’un projet. Un projet informatique peut se dérouler sur plusieurs branches avec une branche principale (retraçant l’évolution du code officiel ou original) et plusieurs branches de développement sur lesquelles des modifications plus radicales peuvent être opérées sans altérer le code officiel.
Premiers pas et Installation de Git
L’installation de Git est aussi simple qu’installer n’importe quel logiciel classique:
- Se rendre sur https://git-scm.com/downloads
- Télécharger et installer la version de logiciel correspondant à votre système d’exploitation
A la fin du processus d’installation, vous devriez être en mesure d’exécuter sans erreur la commande ‘git’ depuis n’importe quel terminal (invite de commande).
Avant de pouvoir utiliser ‘Git’, il est nécessaire d’effectuer quelques étape de configuration afin de pouvoir l’utiliser avec plus d’aisance :
# sets up Git with your name
git config --global user.name "<Your-Full-Name>"
# sets up Git with your email
git config --global user.email "<your-email-address>"
# makes sure that Git output is colored
git config --global color.ui auto
# displays the original state in a conflict
git config --global merge.conflictstyle diff3
# print general properties
git config –list
# print general properties
git config --list
En option, il est également possible de créer un tunnel SSH (Secure Shell) entre votre ordinateur local et votre compte Github grâce aux étapes suivantes:
Création d’une clé privée en écrivant la commande ci-dessous :
ssh-keygen -t rsa -C "votre_email@example.com"
Cette commande va créer un fichier id_rsa.pub dans le répertoire
C:\Users\username\.ssh
Ajout de la clé privée à votre compte Github avec la procédure ci-dessous :
- Connectez-vous à votre compte github: Account Settings et aller dans les paramètres
- Cliquer sur “SSH and GPG keys” sur la gauche
- Cliquer sur “New SSH key” sur la droite
- Donner un nom (par exemple “My laptop”) et coller la clé dans la zone de texte.
- Ensuite dans un terminal, entrer la commande suivante:
$ ssh -T git@github.com
- Si vous avez le message suivant, cela veut dire tout s’est bien passé :
Hi username! You've successfully authenticated, but Github does not provide shell access.
Les commandes git
Création d’un répertoire (Repository) : git init
La création d’un ‘repository’ avec Git s’effectue avec la commande ‘git init’ (voir la documentation) depuis un dossier créé localement. Il est donc nécessaire avant d’exécuter la commande de création d’un dossier ou de se trouver dans le dossier local nouvellement créé.
Les commandes usuelles pour naviguer et créer des dossiers localement sont :
ls - pour lister les fichiers et les dossiers
mkdir - pour créer les dossiers
cd - pour changer de dossier
rm - pour supprimer les dossiers
La commande git init permet de créer tous les fichiers et dossiers nécessaires utilisés par git pour assurer le suivi des différentes versions de fichiers. Tous les fichiers créés sont contenus dans un répertoire appelé .git. C’est dans ce dossier que sont enregistrés tous les résultats de la commande commit (que nous verrons dans la suite).
Ci-dessous une liste de fichiers et répertoires contenus dans le dossier .git :
- config file – contenant tous les éléments de configuration utilisés pour le projet (ex: l’adresse email souhaitée pour le projet)
- description file – utilisé par le programme GitWeb
- hooks directory – pour enregistrer toutes les clés de connexion à des systèmes divers
- info directory
- objects directory – enregistrement de tous les commits
- refs directory
Copie d’un repository: git clone
La commande git clone (voir la documentation et un tutoriel) est utilisée pour créer une copie locale identique d’un répertoire distant existant. La copie d’un répertoire distant s’effectue en utilisant l’URL du répertoire en question souvent de la forme:
https://github.com//
On peut alors utiliser la commande:
$ git clone <chemin-du-répertoire-a-cloner>
La commande va:
- Prendre l’URL (le chemin d’accès d’un répertoire dans le cloud) d’un ‘repository’ existant à cloner
- Créer par défaut un répertoire local avec le même nom que le répertoire distant
- Créer un nouveau répertoire dans le répertoire courant (celui dans lequel on se trouve au moment de l’exécution de la commande)
La commande peut également prendre un second argument correspondant au nom du répertoire local qui sera créé.
Déterminer le statut du répertoire : git status
La commande git status va permettre d’afficher le statut du répertoire ou l’état de vos fichiers à un moment donné. Cette commande est d’une importance capitale lorsqu’il s’agit de savoir s’il y a eu un changement dans le répertoire et si une mise à jour est donc nécessaire avec le répertoire central.
Entre autres, l’utilisation de la commande :
- Renseigne sur l’existence de fichiers créés dans le répertoire de travail (working directory) qui n’auraient pas encore été pris en compte dans l’historique
- Renseigne sur les modifications éventuelles des fichiers suivis dans l’historique
- Donne la branche sur laquelle on se trouve
Cette commande est donc la première que l’on doit exécuter juste après avoir cloné un dossier (c’est-à-dire utilisé la commande git clone) ou en revenant travailler sur un projet après une longue période pour s’assurer qu’on part d’un état stable.
Si d’aventure en exécutant la commande on avait l’affichage suivant :
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
Cela signifierait donc que l’on est bien sur un état stable.
Afficher de l’historique des modifications: git log | git show
La commande git log permet d’afficher l’historique de toutes les modifications du répertoire.
L’utilisation de la commande va par défaut afficher les informations ci-dessous (et ce pour tous les commits effectués):
- L’identifiant SHAI
- Le nom de l’auteur du commits (auteur du changement)
- La date du commits
- La description du commit (ou message associé au commit)
Une fois utilisé, on pourra utiliser les commandes de navigation ci-dessous pour parcourir l’historique:
- j ou ↓ pour descendre
- k or ↑ pour monter
- La barre d’espace ou la commande saut de page pour descendre d’une page
- b pour monter d’une page
- q pour quitter l’historique
Il existe une variante de la commande pour afficher l’historique de chaque commit sur une seule ligne. Pour ce faire, on utilise la commande git log –oneline qui :
- Affiche une seule ligne par commit
- N’affiche que les 7 premiers caractères de l’identifiant SHA
- Affiche la description du commit
Il existe d’autres variantes comme par exemple pour analyser les commits en profondeur (git log –stat ou git log -p). Ces commandes permettent de modifier l’affichage de l’historique pour soit afficher des statistiques sur les modifications ou les modifications elles-mêmes.
Par ailleurs, il est également possible de ne se concentrer que sur un seul commit en spécifiant les premiers caractères de l’identifiant SHAI à la suite de git log -p (ex: git log -p fdf5493).
Une autre commande alternative permettant l’affichage des détails d’un commit est la commande git show toujours en spécifiant l’identifiant SHAI (ex: git show fdf5493)
Ajouter des modifications dans la zone tampon : git add
Supposons un instant que vous avez déjà créé une copie du répertoire distant en local sur votre ordinateur (avec la commande git clone). Vous avez ensuite bien vérifié que vous partiez d’un état stable (avec git status) avant de créer ou modifier des fichiers dans le répertoire local.
Vous souhaitez donc désormais reporter vos modifications dans le répertoire distant. Le report des modifications dans le répertoire distant peut se faire par l’intermédiaire du répertoire tampon (staging area). Il est donc nécessaire d’ajouter en premier lieu les modifications (pouvant être soit des modifications ou des créations de fichiers) dans la zone tampon.
Pour ce faire, on utilise la commande git add <fichier 1> <fichier 2> … <fichier N> pour ajouter les N fichiers dans la zone tampon.
On peut également de manière alternative utiliser la commande git add . pour ajouter tous les fichiers du répertoire de travail.
Il est conseillé après l’utilisation de la commande git add de toujours vérifier l’état global avec la commande git status pour vérifier que tous les changements ont bien été pris en compte.
Ajout des modifications dans le répertoire distante (repository): git commit | git tag
Après l’ajout des modifications dans la zone tampon, il est désormais possible de reporter les modifications dans le répertoire distant (le repository) en utilisant la commande git commit -m <description de la modification>.
L’exécution de cette commande va prendre les dernières modifications présentes dans la zone tampon pour mettre à jour le répertoire distant. Il est alors conseillé d’ajouter après le paramètre -m, une description succincte de la modification ayant eu lieu. Il est également conseillé de ne réaliser qu’une seule modification à la fois pour un meilleur suivi.
En plus d’une description de la modification, il est possible d’ajouter un tag (marqueur spécifique) à un commit avec la commande git tag -a <marqueur>. L’ajout de tag permet d’associer à un identifiant SHAI de commit un point de repère. L’affichage de tag s’effectue avec la commande git log ou git log –decorate. La suppression d’un tag s’effectue avec la commande git tag -d <marqueur>.
Comparer des modifications avant leur pris en compte dans le répertoire distant: git diff
Pour observer des changements ayant eu lieu mais n’ayant pas encore été pris en compte dans le répertoire distant (donc avant l’exécution de la commande git commit) on peut utiliser la commande git diff qui va permettre l’affichage:
- des fichiers ayant été modifiés
- des localisations des lignes de fichiers ayant été modifiées ou enlevées
- des changements effectués
Les ramifications
L’une des forces de git est que ce langage offre les possibilités de travailler avec différentes versions d’un code source. Chaque version peut alors se trouver sur ce que l’on a appelé une branche ou ramification. Dans une branche, chaque modification a été enregistrée avec l’utilisation de la commande git commit qui a permis d’associer un identifiant SHAI unique à chaque changement opéré.
Dans l’exemple ci-dessus on peut voir qu’à partir du commit avec l’identifiant ‘3’, une branche secondaire a été créée pour par exemple tester ou développer une nouvelle fonctionnalité. Les modifications qui seront apportées sur la branche secondaire n’auront ainsi aucun impact sur la branche principale.
Savoir naviguer entre les branches ou les ramifications nécessite l’utilisation de nouvelles commandes en complément de celles déjà utilisées ci-dessus.
Création de nouvelles branches et navigations entre les branches: git branch | git checkout
Pour créer une branche on utilise la commande git branch <nom de la branche>. Une fois exécutée, une nouvelle branche est créée à partir du dernier commit (ou du dernier identifiant SHAI). Il est possible de spécifier le commit à partir duquel on souhaite diverger en utilisant la commande git branch > (ex : git branch alt-sidebar-loc 42a69f).
Pour afficher la branche sur laquelle on se trouve, on peut utiliser la commande git log vu précédemment ou la commande git branch.
Une fois la branche créée, on peut utiliser la commande git checkout <nom de la branche> pour changer de branche et commencer les modifications.Pour supprimer une branche dont on ne sert plus on peut utiliser la commande git branch -d <nom de la branche>.
Il est important de noter qu’après la création d’une branche, les différentes modifications peuvent intervenir de manière tout à fait différentes et isolées sur chacune des branches.
Si l’objectif est de rassembler les différentes versions ultérieurement, il est donc conseillé de créer des branches pour effectuer des modifications sur des parties différentes du code pour éviter tout conflit.L’affichage de toutes les branches en cours peut s’effectuer avec la commande : git log –oneline –decorate –graph –all
L’union fait la force : git merge
On a vu ci-dessus qu’avec les branches il est possible de conserver l’historique d’autant de versions que l’on souhaite d’un code source. L’idée est de permettre aux développeurs de travailler sur différentes fonctionnalités tout en conservant l’historique des modifications de l’ensemble de l’équipe.
La phase de développement arrivant à son terme vient alors le moment de rassembler les différentes fonctionnalités dans un seul et même code. Pour rassembler toutes les branches dans une seule et même branche (typiquement la branche principale ou master), on utilise la commande git merge <nom de la branche à fusionner>. Cette commande permet de rassembler l’ensemble des modifications et l’ensemble de l’historique sur une seule branche.
Cependant, pour que la commande fonctionne correctement, il est important de se positionner sur la branche racine sur laquelle on souhaite réaliser la fusion. la fusion s’effectue donc en deux étape :
- se positionner sur la branche racine sur laquelle on souhaite réaliser la fusion
- utiliser la commande git merge <nom de la branche à fusionner>
Il pourrait arriver dans certains cas que la branche que l’on souhaite utiliser pour réaliser la fusion est en avance par rapport à la branche racine (c’est-à- dire contient certaines opérations que la branche racine n’ a pas encore dans son historique). L’opération de fusion (qui s’effectue comme précédemment) porte alors le nom de ‘fast forward merge’.
Exemple d’un cas d’usage typique
Avec toutes commandes git ci-dessus, il est possible de travailler sur n’importe quel projet de développement. Les possibilités d’utilisation vont fortement dépendre de la complexité du projet et de la maturité des équipes en ce qui concerne le contrôle de version. La taille de l’équipe sera également un facteur non négligeable et il conviendra au tout début du projet d’adopter les bonnes pratiques.
Supposons par exemple que l’on souhaite déployer une application permettant de détecter des éléments tels que qu’un visage, un sourire ou des yeux sur une photo. En règle générale, les étapes à suivre dans le cadre d’une utilisation typique sont décrites ci-dessous :
Step 1 : création du répertoire distant (repository)
Dans votre compte cliquer sur repository puis sur new.
Donner un nom à votre repository, puis ajouter un fichier README. Ce dernier fichier vous permettra de décrire et de documenter votre projet pour faciliter la compréhension et l’utilisation de votre application.
Sur la fenêtre ci-dessous (qui s’ouvrira après avoir cliqué sur ‘create repository’), copier l’URL commençant par git@…
Step 2 : création d’un répertoire de travail local (working directory)
Sur votre ordinateur créer ou naviguer vers un répertoire dans lequel vous souhaitez créer une copie de votre répertoire distant et utiliser la commande git clone suivi de l’URL ci-dessus. Cette commande va créer une copie du répertoire distant en local sur votre ordinateur.
Une fois que la commande aura été exécutée, un dossier portant exactement le même nom que le répertoire distant apparaîtra (chose qu’il est possible de vérifier avec la commande dir.
Le répertoire de travail est donc désormais disponible en local. Il est alors désormais possible d’y copier l’ensemble des fichiers de notre application.
Step 3 : ajout des fichiers de travaux dans la zone tampon
Après avoir copié les différents fichiers de notre application dans le répertoire de travail, il est toujours conseillé d’utiliser la commande git status pour observer les modifications avant la synchronisation avec le répertoire distant.
On peut voir sur l’image ci-dessus que des fichiers ont bien été ajoutés dans le répertoire de travail. Cependant, git nous indique qu’il n’a pas encore commencé à suivre l’évolution de ces fichiers au travers de son historique.
Pour l’instant, ces fichiers ne sont disponibles que dans le répertoire de travail. On peut alors utiliser la commande git add * pour ajouter l’ensemble des fichiers dans la zone tampon et ainsi permettre à git de commencer le suivi de l’historique de ces derniers. Comme précédemment, on devra encore utiliser la commande git status pour bien s’assurer de la manipulation que l’on vient d’effectuer (étant donné que la commande git add ne renvoie aucune sortie).
La dernière exécution de la commande git git status nous montre bien que la synchronisation est désormais possible avec le répertoire distant.
Step 4 : synchronisation avec le répertoire distant
La synchronisation se fait avec l’enchaînement des commandes :
- git commit -m “Ajout des fichiers de la V0”
- git status
- git push
La dernière commande permet de ‘publier’ nos modifications dans le répertoire distant. Cette action est nécessaire au regard du dernier git status (ci-dessous) qui souligne que notre répertoire local est en avance par rapport au répertoire distant.
Si on repart sur le répertoire distant, on pourra voir désormais apparaître les fichiers que nous avions il y a encore 5 minutes seulement localement.