Git Hooks — Automatiser le contrôle qualité
Module 05 45 min
Objectifs de la section
- Comprendre ce que sont les hooks Git et comment ils fonctionnent
- Créer des hooks
pre-commit,commit-msgetpre-push - Partager les hooks avec l'équipe via des outils
- Utiliser
huskypour les projets JavaScript/Node.js
Qu'est-ce qu'un hook Git ?
Les hooks Git sont des scripts qui s'exécutent automatiquement lors d'événements Git (commit, push, merge...). Ils permettent d'automatiser :
- La vérification du format des messages de commit
- Le linting et le formatage du code
- L'exécution des tests avant un push
- La validation des changements
Où sont les hooks ?
# Les hooks sont dans .git/hooks/
ls .git/hooks/
# applypatch-msg.sample
# commit-msg.sample
# pre-commit.sample
# pre-push.sample
# ...
# Activer un hook : supprimer l'extension .sample
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Les hooks les plus utiles
1. pre-commit — Avant le commit
S'exécute avant l'enregistrement du commit. Si le script retourne un code d'erreur, le commit est annulé.
#!/bin/bash
# .git/hooks/pre-commit
echo "Exécution des vérifications pre-commit..."
# Vérification 1 : Pas de fichiers .env commités
if git diff --cached --name-only | grep -E "\.env$|\.env\.local$"; then
echo "ERREUR : Fichier .env détecté ! Ne commitez jamais les fichiers d'environnement."
exit 1
fi
# Vérification 2 : Linting Python (si pylint est installé)
if command -v pylint &> /dev/null; then
FICHIERS_PY=$(git diff --cached --name-only --diff-filter=ACM | grep "\.py$")
if [ -n "$FICHIERS_PY" ]; then
pylint $FICHIERS_PY
if [ $? -ne 0 ]; then
echo "ERREUR : Le linting a échoué. Corrigez les erreurs avant de commiter."
exit 1
fi
fi
fi
# Vérification 3 : Tests Python
if command -v pytest &> /dev/null; then
pytest tests/ --tb=short -q
if [ $? -ne 0 ]; then
echo "ERREUR : Des tests ont échoué. Corrigez-les avant de commiter."
exit 1
fi
fi
echo "Toutes les vérifications pre-commit ont réussi ✅"
exit 0
2. commit-msg — Valider le message de commit
#!/bin/bash
# .git/hooks/commit-msg
FICHIER_MSG_COMMIT="$1"
MESSAGE=$(cat "$FICHIER_MSG_COMMIT")
# Vérifier le format Conventional Commits
# Pattern : type(portée optionnelle): description
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|ci|revert)(\(.+\))?: .{1,72}"
if ! echo "$MESSAGE" | grep -qE "$PATTERN"; then
echo "ERREUR : Message de commit invalide !"
echo ""
echo "Format requis : type(portée): description"
echo "Types valides : feat, fix, docs, style, refactor, test, chore, perf, ci, revert"
echo ""
echo "Exemples :"
echo " feat(auth): ajouter le formulaire de connexion"
echo " fix(api): corriger la validation email"
echo " docs: mettre à jour le README"
echo ""
echo "Votre message : $MESSAGE"
exit 1
fi
# Vérifier la longueur du sujet (max 72 caractères)
SUJET=$(echo "$MESSAGE" | head -1)
if [ ${#SUJET} -gt 72 ]; then
echo "ERREUR : Le sujet du commit est trop long (${#SUJET}/72 caractères)"
exit 1
fi
echo "Message de commit valide ✅"
exit 0
3. pre-push — Avant le push
#!/bin/bash
# .git/hooks/pre-push
echo "Exécution des vérifications pre-push..."
# Exécuter la suite de tests complète
pytest tests/ -v
if [ $? -ne 0 ]; then
echo "ERREUR : Des tests ont échoué. Corrigez avant de pousser."
exit 1
fi
# Vérifier la couverture de code
pytest tests/ --cov=src --cov-report=term-missing --cov-fail-under=70
if [ $? -ne 0 ]; then
echo "AVERTISSEMENT : La couverture de code est inférieure à 70%"
exit 1
fi
echo "Toutes les vérifications pre-push ont réussi ✅"
exit 0
Partager les hooks avec l'équipe
Problème : Le dossier .git/hooks/ n'est pas versionné, donc les hooks ne se partagent pas automatiquement.
Solution : Stocker les hooks dans un dossier versionné et les lier.
# Créer un dossier pour les hooks dans le dépôt
mkdir -p .githooks
# Copier vos hooks
cp .git/hooks/pre-commit .githooks/pre-commit
cp .git/hooks/commit-msg .githooks/commit-msg
# Configurer Git pour utiliser ce dossier
git config core.hooksPath .githooks
# Rendre les hooks exécutables
chmod +x .githooks/*
# Commiter les hooks
git add .githooks/
git commit -m "chore: ajouter les hooks Git de l'équipe"
Ajoutez dans votre README.md :
## Configuration du projet
Après avoir cloné le dépôt, configurez les hooks :
```bash
git config core.hooksPath .githooks
chmod +x .githooks/*
---
## Husky — Hooks pour projets Node.js
Pour les projets JavaScript/Node.js, **Husky** gère les hooks automatiquement :
```bash
# Installer Husky
npm install --save-dev husky
# Initialiser Husky
npx husky init
# Créer le hook pre-commit
echo "npm test" > .husky/pre-commit
# Créer le hook commit-msg (avec commitlint)
npm install --save-dev @commitlint/cli @commitlint/config-conventional
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
Désactiver temporairement les hooks
# Désactiver un hook pour un commit spécifique (cas d'urgence)
git commit --no-verify -m "fix: correction urgente en prod"
git push --no-verify
# Désactiver tous les hooks globalement
git config --global core.hooksPath /dev/null
# (à ne faire qu'en cas d'urgence absolue !)
Résumé
| Hook | Quand s'exécute | Cas d'utilisation |
|---|---|---|
pre-commit | Avant chaque commit | Linting, tests, vérification de secrets |
commit-msg | Après la saisie du message | Valider le format du message |
pre-push | Avant chaque push | Tests complets, couverture |
post-merge | Après un merge | Installer les nouvelles dépendances |
prepare-commit-msg | Avant l'éditeur | Pré-remplir le message |