Introduction
Comme expliqué dans le précédent article sur le système SVN, les systèmes de gestion de version visent à maintenir les versions du code source d’un projet de développement en permettant à tout moment de restaurer une version précédente en cas de régression par exemple, suivre les modifications apportées à chaque version, Quand ? Par qui ? Dans quel fichier ? Et à quelle ligne ? Et donc faciliter le développement du projet par plusieurs intervenants en parallèle.
L’article d’aujourd’hui sera autour du système Git qui est devenu le leader des systèmes de gestion de versions, pas étonnant puisqu’il a été conçu par le célèbre créateur du noyau Linux Linus Torvalds en 2005.
En effet, ce dernier qui utilisait le logiciel Bitkeeper pour gérer le flux d’intégration des patchs du noyau Linux décida de l’abandonner pour des raisons de coût de licence.
Plusieurs personnes ont alors proposé à Linus Torvald d’utiliser le système Subversion (SVN), une idée qui ne plaisait pas à Linus car pour lui, les systèmes CVS est SVN ont plusieurs lacunes et leur conception n’est pas cohérente ne répondant pas aux besoins de gestion des patchs du noyau Linux (voir la video suivante).
Une raison parmi d’autres et que les systèmes CVS et SVN étaient des systèmes centralisés.
Ainsi, Linus Torvalds décide de créer un système de gestion de versions décentralisé qu’il baptisa GIT.
Système de gestion de versions centralisé
- Vous agissez en mode client/serveur sur un seul dépôt centrale partagé.
- Chaque développeur récupère une copie de travail local.
- Chaque développeur doit pousser ses modifications au dépôt central.
- Vous devez avoir un accès réseau au dépôt centrale pour pouvoir valider votre code (dépendance du serveur).
On préfère les systèmes centralisés pour des petits projets. Ils sont simples à gérer et réduisent les chances de conflits. Chaque développeur doit traiter des évolutions courtes et les valider/envoyer rapidement. Un profil plus expérimenté devrait contrôler chaque validation/envoi.
Système de gestion de versions décentralisé
Les systèmes de gestion de versions décentralisés les plus connus sont GIT et Mercurial.
- Vous agissez en mode peer to peer et n’avez pas de dépôt central unique.
- Introduit les notions de dépôt distant (remote) et dépôt local.
- Vous récupérer le dépôt distant et pouvez valider/envoyer votre code en local (Pas de dépendance du serveur)
- Ne nécessite un accès réseau au dépôt distant que lors des opérations de push/pull
Installation de GIT
Pour installer GIT sur Windows, rien de plus simple :
- Télécharger l’exécutable GIT disponible sur le site officiel https://git-scm.com/
- Lancer l’exécutable et suivez les instructions d’installation standard
- Ouvrir une fenêtre du terminal GIT BASH et lancer la commande git –version
Vous devez ensuite personnaliser votre environnement GIT à l’aide la commande git config. Cette étape est à réaliser une seule fois au début.
git config --global user.name "user" git config --global user.email [email protected]
Création d’un nouveau Repository
Git vous donne la possibilité d’initialiser un dépôt git dans un répertoire existant.
Pour cela, il vous suffit de vous déplacer dans le dossier de votre projet et lancer la commande git init.
user@MaMachine MINGW64 ~/Desktop $ mkdir test user@MaMachine MINGW64 ~/Desktop $ cd test user@MaMachine MINGW64 ~/Desktop/test $ ll -a total 16 drwxr-xr-x 1 Hilal 197121 0 nov. 18 16:12 ./ drwxr-xr-x 1 Hilal 197121 0 nov. 18 16:12 ../ user@MaMachine MINGW64 ~/Desktop/test $ git init Initialized empty Git repository in C:/Users/Hilal Issam/Desktop/test/.git/ user@MaMachine MINGW64 ~/Desktop/test (master) $ ll -a total 20 drwxr-xr-x 1 Hilal 197121 0 nov. 18 16:12 ./ drwxr-xr-x 1 Hilal 197121 0 nov. 18 16:12 ../ drwxr-xr-x 1 Hilal 197121 0 nov. 18 16:12 .git/
Comme vous l’avez remarqué en rouge, la commande git init crée un nouveau sous-répertoire nommé .git qui contient tous les fichiers nécessaires au dépôt. La commande créera aussi une branche par défaut nommé master.
Les opérations de base
git init
Nous avons vu l’utilisation de la commande git init. Maintenant, créons un nouveau fichier qu’on va nommer file1.
user@MaMachine MINGW64 ~/Desktop/test (master) $ touch file1
git status
En utilisant la commande git status qui vérifie l’état des fichiers, git nous informe qu’un fichier nommé file1 est non suivi.
user@MaMachine MINGW64 ~/Desktop/test (master) $ git status On branch master No commits yet Untracked files: (use "git add ..." to include in what will be committed) file1 nothing added to commit but untracked files present (use "git add" to track)
git add
La commande git add permet de mettre le fichier file1 en suivi de version.
user@MaMachine MINGW64 ~/Desktop/test (master) $ git add file1
git commit
On pourra ensuite valider notre opération à l’aide la commande git commit qui affichera un récapitulatif des modifications apportées. Notez que les bonnes pratiques encouragent à définir un message à chaque commit résumant la modification apportée.
user@MaMachine MINGW64 ~/Desktop/test (master) $ git commit -a -m "ajout du fichier file1" [master (root-commit) 505c5f6] ajout du fichier file1 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 file1
git log
La commande git log permet de lister les commit effectués. Chaque commit se caractérise par une somme de contrôle SHA-1, le nom et l’e-mail de l’auteur, la date et le message du commit
user@MaMachine MINGW64 ~/Desktop/test (master) $ git log commit 505c5f6ec2effe80fcf8569752630292424f2cde (HEAD -> master) Author: user <[email protected]> Date: Sun Nov 18 17:42:32 2018 +0100 ajout du fichier file1
Création d’un dépôt distant
Jusqu’ici, nous avons créé un dépôt local et toutes les modifications sont en local. Il est temps de les pousser vers un dépôt distant.
Un dépôt distant peut être créé dans votre environnement git d’entreprise. Sinon, vous pouvez en créer un sur le site Github. Seul inconvénient, les comptes gratuits ne peuvent créer que des dépôts public et votre code source pourra être visualisé par tout le monde.
Personnellement, j’utilise le site Bitbucket qui vous permet de créer des dépôts privés gratuitement.
Bitbucket vous affichera un ensemble d’informations nécessaires pour récupérer le dépôt en local.
Il vous suffit donc de suivre les étapes qui vous sont affichées pour saisir l’url du dépôt distant et envoyer le code local vers ce dernier.
user@MaMachine MINGW64 ~/Desktop/test (master) $ git remote add origin https://[email protected]/issamo12/sitedetout_project.git user@MaMachine MINGW64 ~/Desktop/test (master) $ git push -u origin master Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Writing objects: 100% (3/3), 222 bytes | 222.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To https://bitbucket.org/issamo12/sitedetout_project.git * [new branch] master -> master Branch 'master' set up to track remote branch 'master' from 'origin'.
En revenant sur le site Bitbucket, on peut bien voir que notre branche master est disponible sur le dépôt distant.
git clone
Imaginons à présent qu’un collègue se joint à vous pour développer une nouvelle fonctionnalité. Il devra récupérer la dernière version du code source de votre projet.
La commande git clone lui servira à récupérer le dépôt disponible sur Bitbucket.
user2@MachineUser2 MINGW64 ~/Desktop $ git clone https://[email protected]/issamo12/sitedetout_project.git Cloning into 'sitedetout_project'... remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. user2@MachineUser2 MINGW64 ~/Desktop $ cd sitedetout_project/ user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ ll total 0 -rw-r--r-- 1 Hilal 197121 0 nov. 19 10:46 file1
Vous pouvez bien vérifier l’existence du fichier file1 créé par le premier utilisateur.
git pull
Pour récupérer les prochaines modifications du premier utilisateur, il faudra utiliser la commande git pull qui met à jour le dépôt local.
Les branches avec Git
Comme son nom l’indique, une branche permet de diverger du code principale et de créer une ligne de développement parallèle.
Les bonnes pratiques disent qu’il faut créer une branche pour chaque nouvelle fonctionnalité à développer. Ceci permet une meilleur organisation sans polluer la branche principale.
Lorsque vous terminez le développement de la nouvelle fonctionnalité, vous pourrez alors fusionner votre code avec la branche principale ou une autre branche si besoin.
Avec GIT, chaque développeur peut avoir autant de branches privées que souhaité.
git branch
l’utilisateur user2 qui vient de récupérer le dépôt en local souhaite développer une nouvelle fonctionnalité, il va alors créer une nouvelle branche appelée nouvellefonctionnalite.
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git branch nouvellefonctionnalite
git checkout
La commande git checkout permet de nous déplacer sur la branche souhaitée
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git checkout nouvellefonctionnalite Switched to branch 'nouvellefonctionnalite' user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (nouvellefonctionnalite) $ touch newfile user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (nouvellefonctionnalite) $ git add newfile user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (nouvellefonctionnalite) $ git commit -a -m "ajour de newfile" [nouvellefonctionnalite dd0c443] ajour de newfile 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 newfile
git merge
Supposons que le développement de la nouvelle fonctionnalité est terminé. Il est temps de fusionner cette branche avec la branche master à l’aide de la commande git merge.
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (nouvellefonctionnalite) $ git checkout master Switched to branch 'master' Your branch is up to date with 'origin/master'. user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git merge nouvellefonctionnalite Updating 505c5f6..dd0c443 Fast-forward newfile | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 newfile user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git push Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 4 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 251 bytes | 251.00 KiB/s, done. Total 2 (delta 0), reused 0 (delta 0) To https://bitbucket.org/issamo12/sitedetout_project.git 505c5f6..dd0c443 master -> master
Après la fusion, la branche locale peut être supprimée sans crainte.
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git branch -d nouvellefonctionnalite Deleted branch nouvellefonctionnalite (was dd0c443).
Autre sénario
Parfois les développeurs ne font pas de fusion eux mêmes. Après avoir fini de développer leur fonctionnalité dans une branche séparée, il doivent envoyer leur branche au dépôt distant et créer une Pull Request. Un profil plus expérimenté (chef de projet technique ou architecte) s’occupera d’analyser le code envoyé et fusionner la branche avec la branche principale.
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (nouvellefonctionnalite) $ git push -u origin nouvellefonctionnalite Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 4 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 253 bytes | 253.00 KiB/s, done. Total 2 (delta 0), reused 0 (delta 0) remote: Create pull request for nouvellefonctionnalite: remote: https://bitbucket.org/issamo12/sitedetout_project/pull-requests/new?source=nouvellefonctionnalite&t=1 To https://bitbucket.org/issamo12/sitedetout_project.git * [new branch] nouvellefonctionnalite -> nouvellefonctionnalite Branch 'nouvellefonctionnalite' set up to track remote branch 'nouvellefonctionnalite' from 'origin'.
Comme vous pouvez le voir, la branche est envoyée au dépôt distant.
On recommande de bien décrire l’évolution apportée dans la branche avant de créer la pull request.
Suite à la fusion, la branche nouvellefonctionalite sera supprimée.
Marquer une version
Après plusieurs modifications du code source (correction d’anomalies ou évolutions), vous décidez de livrer une nouvelle version de votre application. GIT vous donne la possibilité d’étiqueter l’état actuel de votre code source avec un numéro de version à l’aide de la commande git tag.
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git tag -a v1.0.0 -m "my version 1.0.0" user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git tag v1.0.0 user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git push --tags Enumerating objects: 8, done. Counting objects: 100% (8/8), done. Delta compression using up to 4 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (8/8), 765 bytes | 765.00 KiB/s, done. Total 8 (delta 1), reused 0 (delta 0) To https://bitbucket.org/issamo12/sitedetout_project.git * [new tag] v1.0.0 -> v1.0.0
Ceci vous permettra à un moment plus tard de revenir à cette version si besoin.
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git checkout v1.0.0 Note: checking out 'v1.0.0'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b HEAD is now at ff0657c adding a new file user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project ((v1.0.0)) $ git checkout master Previous HEAD position was ff0657c adding a new file Switched to branch 'master' Your branch is up to date with 'origin/master'. user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master)
Pour supprimer un tag, utilisez la commande git tag suivante :
user2@MachineUser2 MINGW64 ~/Desktop/sitedetout_project (master) $ git tag -d v1.0.0 Deleted tag 'v1.0.0' (was b90472e)
D’autres commandes utiles
git diff :
Permet d’afficher les modifications qui ne sont pas encore validées et indexées (commit).
git rm fichier :
Permet de supprimer un fichier du répertoire de travail.
git reset –hard id_commit
Permet de revenir à un commit spécifique