Vous est-il déjà arrivé de devoir répéter 100 fois la même chose à un collaborateur, sans que ce dernier en tienne compte ? Nombreux sont ceux qui ont connu cette situation, et si c’est votre cas, vous auriez certainement aimé avoir une solution pour obliger ce collaborateur à agir comme il se doit !
Appliquons cette situation au projet Open Transport. Les règles de contribution du projet Open Transport mentionnent explicitement que le message de commit doit contenir le numéro de l’issue. Cette règle a beau être écrite, il est possible que certains collaborateurs ne la suivent pas. Par conséquent, sans information précise, les collaborateurs sont donc contraints de trouver par eux-mêmes l’issue concernée, voire de refuser la pull request. Dans tous les cas, ces situations génèrent une perte de temps considérable.
Pas de panique, une solution existe ! Git possède un moyen pour automatiser des contrôles et traitements lors des opérations Git. Laissez-moi vous présenter les Hooks !
Découvrez le fonctionnement des hooks
En premier lieu, il est important de comprendre que les hooks peuvent se situer côté client ou côté serveur :
le côté client correspond à ce qui se passe sur le repository Git qui est sur votre poste de travail ;
le côté serveur correspond à ce qui se passe sur le repository Git distant, hébergé sur GitHub par exemple.
Ainsi, les hooks côté client permettent de contrôler ou d’ajouter des traitements jusqu’au moment où les fichiers sont envoyés sur le repository distant. Les hooks côté serveur permettront de contrôler ou d’ajouter des traitements lorsque des fichiers arriveront sur le serveur (par exemple à la suite d’un git push).
La bonne nouvelle pour découvrir les hooks est que Git nous a généreusement fourni un ensemble d’exemples ! Vous les trouverez dans le répertoire .git/hooks accessible via le répertoire racine de votre repository.
Vous devriez avoir un contenu similaire à celui-ci :
$ ls -la total 53 drwxr-xr-x 1 romai 197609 0 Mar 28 18:57 ./ drwxr-xr-x 1 romai 197609 0 Mar 21 15:47 ../ -rwxr-xr-x 1 romai 197609 478 Mar 16 12:47 applypatch-msg.sample* -rwxr-xr-x 1 romai 197609 896 Mar 16 12:47 commit-msg.sample* -rwxr-xr-x 1 romai 197609 4655 Mar 16 12:47 fsmonitor-watchman.sample* -rwxr-xr-x 1 romai 197609 189 Mar 16 12:47 post-update.sample* -rwxr-xr-x 1 romai 197609 424 Mar 16 12:47 pre-applypatch.sample* -rwxr-xr-x 1 romai 197609 1643 Mar 16 12:47 pre-commit.sample* -rwxr-xr-x 1 romai 197609 416 Mar 16 12:47 pre-merge-commit.sample* -rwxr-xr-x 1 romai 197609 1374 Mar 16 12:47 pre-push.sample* -rwxr-xr-x 1 romai 197609 4898 Mar 16 12:47 pre-rebase.sample* -rwxr-xr-x 1 romai 197609 544 Mar 16 12:47 pre-receive.sample* -rwxr-xr-x 1 romai 197609 1492 Mar 16 12:47 prepare-commit-msg.sample* -rwxr-xr-x 1 romai 197609 2783 Mar 16 12:47 push-to-checkout.sample* -rwxr-xr-x 1 romai 197609 3650 Mar 16 12:47 update.sample*
Chaque fichier correspond à un hook utilisable. Je ne vais pas tous vous les présenter, la documentation Git le fait très bien. Il est cependant intéressant de s’arrêter sur les préfixes pre et post. Ils permettent de définir si le hook s’exécute avant ou après une opération.
De ce fait, les hooks préfixés par le mot “pre” peuvent être bloquants pour l’opération ciblée. Bien souvent, ils servent à effectuer des contrôles. Par exemple, dans la liste des hooks disponibles, il y en a un nommé “pre-commit.sample”. Le contenu de ce hook sera déclenché lors d’un commit, et l’exécution a lieu avant le commit.
En revanche, les hooks préfixés par le mot “post” ne seront pas bloquants. Ils s'exécutent après que l’opération ciblée a été réalisée avec succès. Ils nous sont donc très utiles pour appliquer des traitements automatiques, par exemple pour appliquer le workflow Git défini sur notre projet.
Allez, réalisons ensemble notre cas pratique dans le cadre d’Open Transport !
Mettez en place un hook
Reprenons le scénario du début de ce chapitre. Notre objectif est de mettre en place un hook qui contrôlera le message des commits. Si ce message contient le numéro de l’issue alors c’est gagné, sinon le commit est refusé.
Pour ce faire, nous allons adapter un hook existant : commit-msg.sample.
Retrouvez-moi dans la démonstration ci-dessous pour savoir comment faire :
Récapitulons les étapes :
1. J’ai modifié le contenu du fichier commit-msg.sample pour y ajouter le code suivant :
LINE_READ=0 REGEX="^(#)([0-9]+)" while read line; do if [[ "$LINE_READ" == "0" ]]; then if ! [[ $line =~ $REGEX ]]; then echo -e "Votre message de commit ne commence pas par le numéro de l'issue précédée du caractère #" exit 1 fi LINE_READ=$(($LINE_READ + 1)) fi done < $1 1
La variable REGEX contient la regex vérifiant que la chaîne de caractères commence avec un # suivi d’un ou plusieurs chiffres.
La boucle while permet de parcourir les lignes du message de commit. Si la première ligne ne correspond pas à la regex, on sort avec un status 1, ce qui a pour conséquence de stopper le commit.
2. J’ai renommé commit-msg.sample en commit-msg pour activer ce hook.
3. J’ai testé le bon fonctionnement du hook avec un commit sans le numéro d’issue, et un autre avec le numéro d’issue.
Finalement, d’un point de vue purement Git, la fonctionnalité des hooks est assez simple. La complexité réside plutôt dans le fait qu’écrire un hook requiert des compétences de scripting. Cela vous permettra d’apporter une vraie plus-value à vos projets. Aussi, je vous conseille de développer ces compétences ou de vous rapprocher des administrateurs système de votre entreprise pour tirer pleinement profit des hooks !
À vous de jouer
Il est temps pour vous de pratiquer ! Les contributeurs ne reçoivent pas suffisamment de félicitations après un commit, alors vous allez changer ça !
Créez un hook qui s’exécutera après un commit et qui affichera le message suivant : “Félicitations, votre contribution est appréciée par la communauté d’Open Transport ! :-)”.
Testez ce hook en réalisant un commit sur le repository.
Vous avez réussi ? Super ! Sinon, n’hésitez pas à vérifier votre travail en consultant le corrigé.
Pour aller plus loin...
Voilà, ce cours est terminé, et j’ai eu beaucoup de plaisir à vous accompagner dans votre apprentissage de Git et GitHub. Sans aucun doute, il y a encore beaucoup à apprendre, alors voici quelques conseils pour aller plus loin :
Prenez le temps de parler avec d’autres développeurs des pratiques mises en place par les entreprises. De bonnes idées peuvent émerger !
Continuez de vous documenter avec les ressources officielles, comme les sites de Git ou de GitHub.
Explorez d’autres ressources, comme le site web d’Atlassian, ou encore le livre (en anglais) Head First Git.
Terminé, mais il reste encore un chapitre ?
Eh oui ! En bonus, nous vous proposons un ultime chapitre pour prendre en main un client GUI pour manipuler Git. Cela n’a rien d’obligatoire pour être un expert de Git et GitHub mais qui sait, cela peut vous être utile un jour.
En résumé
Les hooks permettent de lancer des scripts personnalisés, et ainsi d’effectuer des contrôles et des traitements lors des opérations Git.
Les hooks côté client sont les scripts exécutés sur votre repository local.
Les hooks côté serveur sont les scripts exécutés sur le repository distant.
Git fournit un ensemble de hooks utilisables et adaptables dans le répertoire .git/hooks.