Git¶
Note
Nous allons nous intéresser à l’aspect gestion de versions de Git: Comment enregistrer l’historique des modifications apportées à un projet.
Le problème¶
Le code est plus souvent lu qu’écrit
—Guido van Rossum
La démarche naturelle quand on commence à travailler longuement sur un projet pour lequel on veut éviter d’effacer et/ou de perdre son code à cause d’une erreur humaine est de dupliquer les fichiers et de créer des versions multiples d’un même fichier qui sont des instantanés à un moment donnée:
- rapport.doc
- rapport_v1.1.doc
- rapport_v1.doc
- rapport_v2.doc
- rapport_v2_beta.doc
- rapport_vfinale.doc
Il s’agit d’une manière très artisanale de procéder et qui est susceptible d’être à la merci d’une erreur humaine.
La version la plus à jour est-elle rapport.doc ou rapport_vfinale.doc ? Et si on avait un fichier rapport_vfinale2.doc ?
La gestion des versions est un travail fastidieux et méthodique, spoiler, les humains ne sont pas doués pour les travaux fastidieux et méthodique.
Laissons cela à la machine et concentrons-nous sur la partie du travail où nous sommes meilleurs que la machine.
Version Control System¶
Initialement il s’agit d’une famille de logiciels dédiés à la gestion de code source pour les projets logiciels et également à la documentation, site web, etc.
Leur objectif est de faciliter le travail collaboratif en simplifiant la facilité d’échange des fichiers et de leurs versions, la traçabilité des modifications et la gestion des conflits.
Il existe deux grandes familles de VCS:
- Systèmes centralisés:
CVS (Concurrent Versioning System) vieillissant
SVN (Subversion) populaire il y a quelques temps déjà
- Systèmes décentralisés:
Git
Mercurial (Hg)
Bazaar (bzr)
Ces derniers présentent de nombreux avantages:
Une sauvegarde (modulo la synchronisation avec un serveur distant)
La conservation de l’historique (nominatif) des fichiers « Qui a fait quoi en somme »
La possibilité de retour en arrière
La fusion des modifications lors du travail collaboratif
La visualisation des changements au cours du temps
A propos de Git¶
Il s’agit d’un logiciel de gestion de versions décentralisé, créé par Linus Torvalds (auteur du noyau Linux), sa popularité s’explique par sa rapidité (mise en oeuvre et exécution), le travail par branches possible.
Celui-ci est assez complexe à utiliser, comme tout les CVS, toutefois quelques commandes suffisent pour une utilisation quotidienne.
Initialement il s’agit d’un logiciel pour Linux, il existe maintenant une version pour Windows.
Attention
L’utitilisation de Git nécessite certaines notions préalables:
Fonctionnement d’un filesystem
Connaissance basique du terminal Linux
Potentiellement, un grand nombre de commandes
Indication
GIT est conçu pour les fichiers de type texte, toutefois il fonctionne aussi bien avec des fichiers binaires (images, bureautique, etc.).
Notion de base¶
- Dépôt - repository
Le répertoire caché
.gitest nommé dépôt (repository), il contient toutes les données dont Git a besoin pour gérer l’historique, seul les commandes Git peuvent modifier son contenu.- Commit
L’historique d’un projet est une séquence de snapshot contenant l’état de tous les fichiers du projet. Il s’agit des commits qui possèdent: - une date - un auteur - une description textuelle
Note
En pratique GIT ne stocke pas la totalité des fichiers pour chaque commit mais seulement les différences par rapport à l’état suivant. Ceci a pour avantage d’être moins coûteux en stockage.
- Copie de travail
Working copy, il s’agit des fichiers présents dans le répertoire géré par Git, leur état peut être différent du dernier commit de l’historique.
- Index
Il s’agit d’un espace temporaire contenant les modifications prêtes à être « commitées ». Ces modifications peuvent être une création de fichier, une modification de fichier ou encore une suppression de fichier.
Utilisation de la commande git¶
$ git init
Note
Initialise la gestion de version dans un répertoire (le répertoire courant) en créant le sous-répertoire .git
$ git status
$ git diff
$ git add <filename>
$ git reset <filename>
$ git commit -m "Ceci est un commentaire pertinent"
Attention
Avant toute utilisation de la commande commit, il convient d’ajouter des éléments à l’index via la commande add
Commande git |
Visualisation dans l’historique |
|---|---|
|
|
|
|
|
|
$ git log
$ git show <commit-id>
Cycle de vie des commandes git en local¶
Dépôt distant¶
Un Remote repository est un dépôt GIT tout à fait similaire à un dépôt local mais accessible via une URL.
Indication
Un dépôt local peut être lié à un dépôt distant
L’utilisation d’un remote repository présente l’intérêt
d’une sauvegarde à distance du projet,
d’un travail sur plusieurs machines
d’un projet accessible facilement
et d’une collaboration à plusieurs sur un projet
Cycle de vie des commandes git via un dépôt distant¶
Sa mise en oeuvre passe par plusieurs étapes:
Créer un dépôt sur un serveur (gitlab.com, framagit.org, github.com, etc.)
Cloner un dépôt distant
Publier des commits
Récupérer les commits
$ git clone <repository-url>
$ git push <repository-name> <branch-name>
Note
repository-name: par défaut
originbranch-name: par défaut
master
Désynchronisation
Le push n’est possible que si la branche locale contient tous les commits de la branche distante.
Si la branche distante contient des commits inconnus en local, il faudra au préalable les récupérer.
$ git pull
Important
Cette opération copie dans le dépôt local les commits distants et met à jour la copie de travail.
Pour éviter les problèmes avec Git¶
- Quand réaliser un commit ?
Dès qu’il y a une avancée du programme qui fonctionne.
Ne pas commiter du code qui ne fonctionne pas.
Le concepteur de Git, Linus Torvalds, préconise de commiter le plus souvent possible.
- Quand réaliser un push ?
Dès que des fonctionnalités deviennent intéressante pour les autres membres de l’équipe.
Afin de pas perturber les autres membres de l’équipe, il faut éviter de réaliser des pushs à répétition.
Il est possible d’éditer un commit avant qu’il ne soit publié.
Une fois qu’un commit est publié : il ne peut plus être modifié.
Ne pas versionner les fichiers inutiles
Tous les fichiers ne doivent pas être soumis au gestionnaire de versions (les fichiers temporaire, le .exe généré par Visual Studio, etc.)
L’utilisation du fichier .gitignore est plus que recommandé notamment par l’utilisation du site gitignore.io pour générer un fichier .gitignore de base.
Les branches¶
Lors du développement d’un logiciel, il est primordial d’introduire une nouvelle fonctionnalité sans « casser » le projet.
On souhaite basculer instantanément de la version stable à la version en développement.
C’est ce que nous permettent de faire les branches.
Note
La branche par défaut master, l’idéale serait de ne jamais commiter dans master.
Il convient de créer des branches feature_{x} lorsque une fonctionnalité est développée (dans la réalité, il y a autant de branche feature que de fonctionnalité à developper).
Pour les corrections urgentes, l’utilisation des branches hotfix_{x} est recommandée.
Ainsi la branche master ne contient que du code propre. Si un utilisateur fait une erreur, il n’impact que sa propre branche : il ne pollue pas l’ensemble du dépôt.
Création de branche¶
$ git branch <NOM>
Depuis la branche parente, souvent master
$ git checkout -b feature_x
$ git checkout master
Fusion de branches¶
Le sprint a été lancé. Une fonctionnalité à été développée, elle est terminée : il faut donc l’intégrer à la branche master.
Avertissement
La fusion se fait sur la branche courante, pensez à changer de branche avant de fusionner !
master¶$ git checkout master
$ git merge feature_x
Note
Si la branche feature_x n’a pas été modifiée depuis le début du développement de la fonctionnalité alors Git intégre les commits de feature_x à master. Il s’agit du merge fast-forward. La branche master et feature_x sont désormais équivalentes, il convient de supprimer feature_x.
Si la branche feature_x avait évolué avant la fin du développement de la fonctionnalité. Le merge fast-forward n’aurait pas été possible !Un nouveau commit aurait été créé par Git pour fusionner les deux branches.
Important
Si on souhaite conserver la branche feature_x distincte de master
$ git merge --no-ff feature_x
Un commit de fusion des deux branches sera créé, l’historique est préservé.
Branches de développement¶
Pour corriger un bug numéroté 1138, nous devons entreprendre les actions suivantes:
Création d’une branche
bugfix_1138à partir de la branche stable (master)Bascule sur la branche
bugfix_1138Correction du bug (commit/push)
Fusion de la branche
bugfix_1138avec la master via la commandemerge
Commande git |
Historique git |
|---|---|
$ git commit -m "Initial commit"
$ git commit -m "Add app.py"
|
|
$ git branch bugfix_1138
$ git checkout bugfix_1138
|
|
$ git commit -m 'Fix issue on int'
|
|
$ git checkout master
$ git merge bugfix_1138
|
|
Une petite mise en jambe avec Git¶
Pour obtenir un dépôt Git sur lequel travailler, deux options sont possibles:
Création d’un dépôt vide,
Copie (clone dans le langage Git) d’un dépôt existant pour travailler sur une copie de travail.
Nous nous intéresserons à la deuxième option qui fait partie de la vie courante d’un développeur.
Git a plusieurs interfaces utilisateur, la plus complète étant l’interface en ligne de commande (CLI) nous nous servirons de celle-ci.
À faire
Tout d’abord il convient de créer un compte sur une forge git comme Gitlab.
Créer un premier repository HelloWorld via l’interface en ligne de Gitlab
Cloner ce repository sur votre ordinateur via la commande
cloneQuel commande utiliser pour afficher le statut de ce dépôt ?
Attention
Attention à partir de maintenant nous n’utiliserons l’interface web de gitlab uniquement pour constater les changements de données sur notre dépot distant. Lorsqu’il vous est demandé de créer des fichiers, il convient de le faire sur votre machine via un éditeur de code.
Astuce
Un fichier readme (en français, lisezmoi) est un fichier contenant des informations sur les autres fichiers du même répertoire. L’extension .md indique qu’il s’agit d’un fichier formaté en Markdown.
À faire
Créer le fichier README.md
Ajouter à ce fichier le contenu suivant:
# HelloWorld
## About
A simple repo for learning git
## Author
Insert your name here
Pour intégrée dans l’historique des révisions du dépôt (pour être « committée »), chaque modification doit suivre le workflow suivant:
Note
La modification est d’abord effectuée sur la copie de travail;
Elle est ensuite mémorisée dans une aire temporaire nommée index avec la commande
git add;Enfin ce qui a été placé dans l’index peut être « committé » avec la commande
git commit
Diagramme UML du Workflow d’une modification avec Git¶
Vérifiez avec git status l’état dans lequel se trouve votre dépôt. Vos modifications (l’ajout du fichier README.md) devraient être présentes seulement dans la copie de travail.
À faire
Préparez README.md pour le commit avec
git add README.md.Utilisez
git statusà nouveau pour vérifier que les modifications ont bien été placées dans l’index.Commitez votre modification avec
git commit -m "<votre_message_de_commit>". Le message entre double quotes décrira la nature de votre modification (généralement inférieur à 65 caractères).Exécutez à nouveau:code:git status, pour vérifier que vos modifications ont bien été commités.
Essayez à présent la commande
git logpour afficher la liste des changements effectués dans ce dépôt ; combien y en a-t-il ? Quel est le numéro (un hash cryptographique en format SHA1) du dernier commit effectué ?
Vos modifications sont prises en compte dans votre dépôt local, toutefois via la commande git status vous pouvez remarquer que le commit n’est pas publié sur le dépôt distant.
Diagramme UML du Workflow d’une modification avec Git¶
À faire
Publiez votre commit avec
git push origin master. Que signifie origin et master ?Exécutez à nouveau
git status, pour vérifier que votre commit a bien été publié.
Une histoire de Burger
Dans note repository nous allons créer un répertoire sandwich qui contiendra le fichier burger.txt.
Le fichier burger.txt contient la liste des ingrédients d’un burger, un ingrédient par ligne.
steak
salade
tomate
cornichon
fromage
À faire
Comment vérifier que ce fichier n’est pas versionné ?
Comment l’ajouter à l’index ?
Comment le « committer » ?
Comment publier ce commit ?
À faire
Créez quelques autres sandwichs hot_dog.txt, jambon_beurre.txt et modifiez les compositions déjà créés, en committant chaque modification séparément.
Chaque commit doit contenir une et une seule création ou modification de fichier. Effectuez au moins 5 modifications différentes (et donc 5 commits différents).
À chaque étape essayez les commandes suivantes :
git diffavantgit addpour observer ce que vous allez ajouter à l’index;git diff --cachedaprèsgit addpour observer ce que vous allez committer.
Regardez maintenant l’historique des modifications avec git log et vérifiez avec git status que vous avez tout commité.
Voyage dans le temps
Vous voulez changer d’avis entre les différents états de la Figure sur l’état des modifications ? Faites une modification d’un ou plusieurs sandwichs, ajoutez-la à l’index avec git add (vérifiez cet ajout avec git status ), mais ne la commitez pas. Exécutez git rest sur le nom de fichier (ou les noms de fichiers) que vous avez préparés pour le commit ; vérifiez avec git status le résultat.
À faire
- Votre modification a été « retirée » de l’index.
Vous pouvez maintenant la jeter à la poubelle avec la commande
git checkoutsur le ou les noms des fichiers modifiés, qui récupère dans l’historique leurs versions correspondant au tout dernier commit.Essayez cette commande, et vérifiez avec
git statusqu’il n’y a maintenant plus aucune modification à commiter.
- Regardez l’historique de votre dépôt avec
git log; choisissez dans la liste un commit (autre que le dernier).
Exécutez
git checkout COMMITIDoùCOMMITIDest le numéro de commit que vous avez choisi.Vérifiez que l’état de vos sandwichs est maintenant revenu en arrière, au moment du commit choisi.
Que dit maintenant
git status?
- Regardez l’historique de votre dépôt avec
Vous pouvez retourner à la version plus récente de votre dépôt avec
git checkout master.Vérifiez que cela est bien le cas. Que dit maintenant
git status?