Objectifs
- Comprendre ce que sont les “hooks” Git et leur utilité pour automatiser des vérifications.
- Mettre en place un hook
pre-commitsimple pour exécuter une action avant chaque commit. - Utiliser un hook pour lancer automatiquement un linter (
shellcheck) et empêcher les commits de code de mauvaise qualité. - Découvrir le hook
pre-pushpour des tests plus longs.
Explications détaillées
Notions clés
Qu’est-ce qu’un hook Git ?
Un hook (crochet en anglais) est un script que Git exécute automatiquement à certains moments clés de son cycle de vie. C’est un mécanisme puissant pour faire respecter des standards de qualité, lancer des tests ou automatiser des tâches sans que le développeur n’ait à y penser.
Où se trouvent les hooks ?
Chaque dépôt Git contient un dossier .git/hooks/. À l’intérieur, vous trouverez une série de fichiers d’exemples se terminant par .sample (ex: pre-commit.sample). Pour activer un hook, il suffit de :
- Créer un fichier exécutable avec le nom correspondant (ex:
pre-commit). - Ou de renommer le fichier d’exemple en enlevant
.sample.
Les hooks sont des scripts locaux : ils ne sont pas versionnés avec le reste de votre projet et ne sont pas transférés lorsque vous clonez un dépôt.
Le hook pre-commit
C’est le hook le plus utilisé. Il est exécuté juste après que vous ayez lancé git commit, mais avant que Git ne vous demande d’écrire un message de commit.
- Si le script
pre-commitse termine avec un code de sortie0(succès), le commit continue. - S’il se termine avec un code de sortie non-nul (échec), le commit est avorté.
C’est l’endroit idéal pour des vérifications rapides : linter, formateur de code, recherche de secrets…
Le hook pre-push
Ce hook est exécuté juste avant que git push n’envoie vos commits vers le dépôt distant. Comme il ne ralentit pas chaque commit, il est adapté pour des tâches plus longues, comme lancer une suite de tests d’intégration.
Le framework pre-commit
Gérer les hooks manuellement peut être fastidieux, surtout en équipe. Des outils comme le framework pre-commit (un outil Python) permettent de gérer une configuration de hooks multi-langages dans un simple fichier .pre-commit-config.yaml que vous pouvez, lui, versionner avec votre projet. C’est la méthode recommandée pour un usage professionnel.
Syntaxe / Usages
# Pour créer un hook pre-commit simple
# 1. Allez dans le dossier des hooks
cd .git/hooks/
# 2. Créez le fichier
touch pre-commit
# 3. Rendez-le exécutable
chmod +x pre-commit
# 4. Modifiez-le avec votre éditeur pour y mettre votre script
Exemples
Exemple 1 : Interdire les commits sur main
Un hook simple pour éviter les erreurs.
Contenu de .git/hooks/pre-commit :
#!/bin/bash
# Récupérer la branche actuelle
branche_actuelle=$(git rev-parse --abbrev-ref HEAD)
if [[ "$branche_actuelle" == "main" ]]; then
echo "Erreur : vous ne pouvez pas commiter directement sur la branche 'main'."
exit 1 # Le code de sortie 1 avorte le commit
fi
exit 0 # Succès, le commit peut continuer
Exemple 2 : Lancer shellcheck sur les fichiers modifiés
Un hook plus réaliste qui analyse les fichiers .sh sur le point d’être commités.
Contenu de .git/hooks/pre-commit :
#!/usr/bin/env bash
set -euo pipefail
# On ne vérifie que les fichiers qui sont 'staged' (ajoutés au commit)
# et qui se terminent par .sh
fichiers_sh_stages=$(git diff --cached --name-only --diff-filter=ACM | grep '\.sh$')
if [[ -z "$fichiers_sh_stages" ]]; then
# Pas de fichier .sh, on sort avec succès
exit 0
fi
echo "Lancement de shellcheck sur les fichiers modifiés..."
# On passe la liste des fichiers à shellcheck
# Le '|| true' est une astuce. shellcheck sort avec un code 1 s'il trouve des erreurs,
# ce qui avorterait notre hook. On gère l'échec nous-mêmes.
if ! shellcheck $fichiers_sh_stages; then
echo "Shellcheck a trouvé des erreurs. Commit avorté."
exit 1
fi
echo "Shellcheck n'a trouvé aucune erreur."
exit 0
Bonnes pratiques
- Gardez vos hooks rapides, surtout
pre-commit. Personne n’aime attendre 30 secondes avant chaque commit. - Les hooks doivent donner des messages clairs. S’ils bloquent un commit, ils doivent expliquer pourquoi et comment corriger le problème.
- Pour partager des hooks en équipe, utilisez un framework dédié comme
pre-commit.
Pièges courants
- Oublier de rendre le hook exécutable (
chmod +x .git/hooks/pre-commit). S’il n’est pas exécutable, Git l’ignorera silencieusement. - Les hooks ne sont pas versionnés. Si un nouveau développeur rejoint le projet, il doit installer les hooks manuellement (ou via une procédure documentée). C’est le principal problème que les frameworks résolvent.
- Un utilisateur peut toujours contourner un hook avec l’option
--no-verify(git commit --no-verify). Les hooks sont une aide, pas une garantie de sécurité infaillible.
Exercices
-
Le hook “pas sur main” :
- Implémentez le hook de l’Exemple 1 qui interdit de commiter sur la branche
main. - Allez sur votre branche
main, modifiez un fichier, et essayez de le commiter. Observez le message d’erreur et l’échec du commit.
- Implémentez le hook de l’Exemple 1 qui interdit de commiter sur la branche
-
Le hook anti-TODO :
- Créez un hook
pre-commitqui cherche le mot “TODO” (en majuscules) dans les fichiers que vous vous apprêtez à commiter. - S’il le trouve, il doit afficher un message d’erreur et avorter le commit. (Indice :
git diff --cached | grep "TODO").
- Créez un hook
-
(Bonus) Installation du framework
pre-commit:- Installez le framework
pre-commit(pip install pre-commit). - Créez un fichier
.pre-commit-config.yamlà la racine de votre projet. - Ajoutez un hook simple comme
trailing-whitespace(qui supprime les espaces en fin de ligne). - Lancez
pre-commit install, puispre-commit run --all-files. - Observez comment il gère les fichiers pour vous.
- Installez le framework