Les git hooks, c’est une pratique qu’on voit de plus en plus dans les projets. On l’adopte souvent parce qu’on l’a vu ailleurs, ou parce que ça semble être une bonne idée pour garantir la qualité du code. Mais est-ce que c’est vraiment le cas ?
Avant d’aller plus loin, il faut expliquer ce qu’est un hook git. Avec git on peut exécuter des scripts lorsqu’on veut créer un commit, push etc (pre-commit, pre-push etc).
💡 sur ses commandes pour ignorer les hooks
L’autre problème c’est que les hooks nous poussent vers du code “parfait” à chaque commit. Mais un commit ce n’est pas une livraison. Prenons un exemple concret : on travaille en TDD, on vient d’écrire un test rouge qui décrit le comportement qu’on veut implémenter. On veut commit ce test avant de passer à l’implémentation. Sauf que le hook pre-commit lance le build ou le linter ou le type check, ça échoue, et le commit est bloqué. On est forcé soit d’implémenter dans la foulée, soit de faire --no-verify. Le cycle red-green-refactor, qui repose justement sur des états intermédiaires, devient pénible.
C’est le principe même du commit : sauvegarder un état pour pouvoir revenir en arrière si besoin. Avec des hooks trop stricts, on nous demande du code parfait à chaque sauvegarde. On perd cette liberté.
Et le problème ne s’arrête pas au commit. Même quand le hook pre-commit se limite au lint et au build, on retrouve souvent les tests dans un hook pre-push. Résultat : on peut commit en local, mais impossible de push tant que les tests ne passent pas. Si on fait du pair ou du mob programming et qu’on veut partager un état de travail en cours, c’est bloqué. Si on a besoin d’un avis d’un collègue sur une approche avant de continuer, c’est bloqué. On retombe dans la même logique : du code “parfait” pour pouvoir collaborer.
Et ce n'est pas le seul problème…
Double pain, zero gain
L’autre problématique qu’on crée avec les hooks, c’est la duplication. Les mêmes vérifications tournent en local via les hooks, puis une deuxième fois dans la pipeline (Github Actions, Gitlab CI etc). On attend que les hooks passent, puis on attend que la CI relance exactement la même chose. On ne gagne pas de temps, on en perd.
Et ce n’est pas juste une question de temps. On se retrouve à maintenir les checks à deux endroits : la config des hooks et la pipeline. On met à jour une option dans une commande côté CI mais on oublie de le faire côté hooks, ou l’inverse. Les deux divergent, et on ne s’en rend compte que quand ça casse.
De plus, on risque de retomber dans le piège du "ça marche sur ma machine", ou justement l’inverse. L’environnement local et la CI ce n’est pas la même chose. Les versions des outils, les dépendances, la config... il y a de nombreuses raisons pour que le résultat soit différent. On se rajoute une charge cognitive en plus pour comprendre pourquoi ça passe chez nous et pas dans la pipeline, ou l’inverse.
Finalement, c’est la CI qui décide si on peut merge ou pas. C’est elle la source de vérité. Si on lui fait confiance pour bloquer un merge, pourquoi dupliquer ce travail en local ?
Mais alors, si les hooks posent autant de problèmes, pourquoi on continue à les utiliser ?
Ce qu'on compense vraiment
Le vrai problème c’est la feedback loop de notre CI. La pipeline prend 20 minutes, on ne reçoit aucune notification en cas d’échec, et surtout, tout reste très obscur. Car on a une grosse étape qui mélange plein de trucs et pour savoir ce qui a cassé on doit aller fouiller dans les logs. C’est frustrant.
Les hooks c’est une réponse à cette frustration. On veut un feedback plus rapide, plus clair, plus proche de nous. Et ça se comprend.
Dans tous les cas, les hooks c’est un pansement, pas une solution. On traite le symptôme mais pas la cause. Le vrai sujet c’est pas "comment avoir un feedback plus vite en local", c’est "pourquoi mon feedback est lent et pas clair à la base".
Si la pipeline met 20 minutes, rajouter des hooks en local ça ne rend pas la pipeline plus rapide. On a juste déplacé le problème. Le jour où le hook passe mais la CI échoue, on est au même point qu’avant, sauf qu’on a perdu du temps en plus.
Et si le feedback de la CI n’est pas clair, c’est rarement un problème d’outillage. C’est souvent qu’on a une grosse étape qui fait trop de choses, que les erreurs sont noyées dans les logs, que personne n’a pris le temps de rendre ça lisible. Les hooks ne résolvent rien de tout ça.
La vraie problématique c’est : comment réduire le temps du feedback loop et le rendre plus clair quand ça échoue. Et la réponse, c’est rarement "rajouter une couche en local". Alors on fait quoi ?
Réparer la source
Plutôt que de compenser en local, on devrait investir dans la Developer eXperience de notre pipeline.
Déjà, découper la CI en étapes claires et parallélisées. Une étape pour le lint, une pour les tests, une pour le build. Si le lint échoue, on le voit tout de suite, on n’a pas besoin d’aller fouiller dans les logs d’une étape monolithique. Et si les étapes tournent en parallèle, on réduit le temps total.
Ensuite, avoir des notifications quand la CI échoue. On ne devrait pas avoir à aller vérifier manuellement si la pipeline est passée. Un message Slack, un mail, une notif Github... peu importe, mais on doit le savoir rapidement.
Et enfin, rendre les erreurs lisibles. Quand ça échoue, on doit comprendre pourquoi en quelques secondes, pas en 5 minutes de lecture de logs. C’est un effort qui se fait une fois et qui profite à toute l’équipe, contrairement aux hooks qui restent une solution individuelle.
💡 Si on veut quand même un hook en attendant d’améliorer la CI, du projet des instructions que l’agent suit à chaque session, comme "lance les tests après chaque modification". Et si le contexte de conversation est compacté et que les instructions risquent d’être perdues, on peut les mettre dans un skill dédié pour être sûr qu’elles sont toujours là.
Reste la question : que se passe-t-il quand ça échoue ? C’est là que ça devient intéressant. Des outils comme Claude Code proposent des hooks de cycle de vie internes à l’agent : on peut configurer un script qui s’exécute quand une commande échoue (par exemple les tests), et qui injecte du contexte dans la conversation de l’agent. Concrètement, quand les tests échouent, au lieu de bloquer le commit, le hook guide l’IA : "Analyse si cet échec est lié à tes changements. Si oui, corrige. Si non, informe le développeur." Ce n’est pas une règle rigide, c’est du guidage. L’IA reçoit le contexte et juge. Si le test qui échoue est directement lié à ce qu’elle vient de modifier, elle le corrige toute seule et continue. Si c’est un test sans rapport, elle commit pour sauvegarder l’état actuel et nous informe : "Ce test a échoué mais ça n’a rien à voir avec mes changements. Tu veux qu’on regarde ensemble ?"
Le git hook applique une règle aveugle — ça passe ou ça bloque, pour tout le monde, sans distinction. Le hook d’agent donne du contexte et laisse le jugement à l’IA, tout en rendant le contrôle au développeur. Et ça ne s’arrête pas au local : l’agent peut aussi réagir aux événements de la CI, recevoir une notification d’échec et analyser ou corriger l’erreur automatiquement.
Concrètement, avec Claude Code, ça ressemble à ça dans le
.claude/settings.jsondu projet :
CODE{
"hooks": {
"PostToolUseFailure": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(npm run test|vitest)",
"command": "echo '{\"additionalContext\": \"Des tests ont échoué. Analyse si ces échecs sont liés à tes changements. Si oui, corrige-les. Si non, commit tes changements et informe le développeur des tests qui échouent sans rapport avec ton travail.\"}'"
}
]
}
]
}
}
Le hook ne se déclenche que quand
npm run testouvitestéchoue. Il n'injecte pas une règle, il injecte du contexte que l'IA utilise pour juger de la marche à suivre.
💡 Pour aller plus loin sur les hooks Claude Code (
PostToolUseFailure,additionalContext,matcher, etc.), la documentation complète est disponible ici : https://code.claude.com/docs/fr/hooks-guide
Un outil, plusieurs contextes
Ce que je décris ici s’applique à un contexte précis : une équipe en entreprise, avec une CI, et des développeurs qui travaillent ensemble au quotidien. Dans ce cadre, les hooks compensent un problème qu’on a les moyens de résoudre autrement.
Mais les git hooks ne viennent pas de nulle part. Ils ont été pensés pour des projets où les contributeurs sont nombreux, de niveaux très différents, et où personne ne maîtrise l’ensemble du projet. C’est exactement le cas de l’open source.
Sur un projet open source, les contraintes sont autres. Les contributeurs ne connaissent pas forcément les conventions du projet, ils ont des setups locaux très différents, et ils ne contribuent parfois qu’une seule fois. Un contributeur occasionnel qui ouvre une PR ne va pas passer 20 minutes à comprendre pourquoi la pipeline a échoué. Si un hook lui corrige le formatage et lui signale une erreur de lint avant même de push, c’est du temps gagné pour tout le monde : pour lui et pour les mainteneurs qui relisent.
Dans ce contexte, les hooks ne compensent pas une mauvaise CI. Ils servent de filet de sécurité accessible, qui réduit le bruit dans les PRs et accélère le feedback pour des gens qui ne contribuent peut-être qu’une seule fois. C’est un usage légitime, et c’est d’ailleurs pour ça qu’on les retrouve dans beaucoup de projets open source bien maintenus. Next.js, Angular, webpack, Storybook, NestJS, Prisma... tous utilisent des hooks pour lancer le formatage et le lint sur les fichiers stagés avant chaque commit. Pas les tests, pas le build. Juste ce qui est rapide et auto-corrigeable.
Les git hooks ce n’est pas un mauvais outil. En open source, c’est un filet de sécurité qui a fait ses preuves. Mais dans une équipe en entreprise, avec une CI et les moyens d’investir dedans, s’en servir pour compenser un feedback loop lent c’est mettre un pansement. Le problème n’est pas en local, il est dans la pipeline. C’est là qu’il faut agir.
↗ Original-Artikel auf dev.to lesenVollständiger Original-BerichtAusführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
SOCIAL SHARE CARD GENERATOR