Hooks pre-commit pour dépôts hérités : garde-fous simples
Configurez des hooks pre-commit pour dépôts hérités avec formatage, linting, scan de secrets et tests rapides pour bloquer les mauvais commits avant que le CI ne s'exécute.

Pourquoi les dépôts hérités continuent de casser
Un dépôt hérité est du code que vous n'avez pas façonné. Les règles sont floues, le style est mélangé, et « ça marche sur ma machine » revient souvent parce que personne ne sait vraiment ce qu'attend le dépôt.
Les problèmes commencent petit et deviennent de vraies pannes : un fichier utilise des tabulations, un autre des espaces ; une correction rapide ajoute une dépendance sans fixer la version ; un fichier de config est édité à la main et s'éloigne de ce que la production attend. Même des changements simples deviennent risqués parce que le repo est plein d'hypothèses cachées.
Se reposer uniquement sur le CI arrive généralement trop tard. CI s'exécute après que le commit est déjà partagé, la revue est déjà lancée et les gens ont déjà récupéré l'état cassé. Quand CI échoue, vous perdez du temps à relancer des pipelines, rebaser et deviner quel changement a déclenché le problème. Au fil du temps, les relecteurs cessent de faire confiance aux signaux parce que les échecs semblent « normaux ».
Le vrai dommage vient de l'empilement de petites erreurs :
- Un minuscule changement de formatage crée des diffs bruyants, et un vrai bug passe à travers.
- Un problème de lint est mis de côté « pour après », puis devient un pattern.
- Un test n'est pas exécuté localement, et une build cassée bloque tout le monde.
- Un secret est commis et déclenche une panique pour faire tourner les clés.
Les hooks pre-commit aident parce qu'ils déplacent les vérifications les plus courantes au point le plus tôt : avant qu'un changement ne devienne un problème partagé. Ils créent aussi une baseline cohérente sans longs débats sur « la bonne façon ».
Quand ça marche, c'est ennuyeux (dans le bon sens) : moins de builds cassés, des diffs plus petits et des merges plus rapides parce que les revues se concentrent sur la logique plutôt que le style.
Ce que les garde-fous pre-commit doivent attraper
Les dépôts hérités échouent de manière prévisible. Le but n'est pas de bloquer chaque commit. C'est d'empêcher les quelques erreurs à fort impact qui créent du bruit, cassent les builds ou fuient des données.
Commencez par le dérèglement du formatage. Les fichiers non formatés génèrent d'énormes diffs qui cachent les vrais changements. Une correction d'une ligne ne devrait pas venir avec 400 lignes de churn d'espaces. Le formatage automatique au commit garde les revues lisibles et rend les merges moins pénibles.
Ensuite, attrapez les problèmes de lint qui indiquent de vrais bugs, pas des opinions de style : variables non définies, imports inutilisés, comparaisons suspectes, await manquants, ou des patterns dangereux comme des requêtes SQL construites par concaténation. Si votre linter n'avertit que pour des virgules, les gens apprendront à l'ignorer.
Les secrets sont la grosse menace. Les clés se glissent quand quelqu'un copie un .env dans le repo, colle un token dans un fichier de config, ou ajoute un log de debug contenant des identifiants. Un scan de secrets doit bloquer le commit avant qu'il n'atteigne un remote.
Enfin, exécutez des tests rapides qui prennent des secondes, pas des minutes. Le meilleur hook est celui que les gens laissent activé. Un petit smoke test, un sous-ensemble unit rapide, ou une vérification de types basique attrapent les régressions évidentes tôt.
Un ensemble pratique de choses à bloquer :
- Changements d'auto-format (pour garder les diffs petits)
- Erreurs de lint à fort signal (probables bugs)
- Secrets détectés (tokens, clés API, clés privées)
- Tests rapides ou vérifications de type (feedback rouge-vert rapide)
- Vérifications de sanity (JSON/YAML valides, cohérence des lockfiles)
Choisir un petit jeu d'outils adapté à votre repo
Quand vous héritez d'un dépôt, l'objectif n'est pas la « couverture maximale ». L'objectif est moins de commits cassés. Commencez avec trois ou quatre vérifications en lesquelles vous avez confiance, puis ajoutez-en après que l'équipe cesse de lutter contre l'outil.
Un bon ensemble de départ :
- Un formateur (corrige automatiquement, pas de débat)
- Un linter (attrape des erreurs réelles, pas le style)
- Un scan de secrets (empêche les clés et tokens de fuir)
- Un test ou une vérification de build rapide (secondes, pas minutes)
Adaptez les outils au langage que vous exécutez réellement. Si vous avez plusieurs langages, scopez les vérifications aux dossiers correspondants pour qu'un côté ne ralentisse pas l'autre.
La vitesse compte plus que la perfection. Si un hook prend 30 à 60 secondes, les gens le contourneront. Préférez des outils prévisibles : même sortie sur toutes les machines, faibles faux positifs et corrections claires.
Décidez ce qui bloque un commit et ce qui ne fait qu'avertir. Bloquer doit être réservé aux choses presque toujours incorrectes (formatage, erreurs de lint évidentes, secrets). Les avertissements conviennent mieux aux règles « peut-être » (limites de complexité, règles de style strictes) jusqu'à ce que le dépôt se stabilise.
Si vous travaillez dans un monorepo, une règle simple aide : exécuter seulement ce qui a changé. Si vous modifiez le dossier API, lancez le lint API et un test API rapide, pas le repo entier.
Étape par étape : ajouter pre-commit à un dépôt hérité
Créez une branche baseline (ou un tag) à partir de la branche main actuelle. Ensuite, lancez les vérifications une fois sur tout le dépôt pour voir l'impact initial. Cette première exécution n'a pas pour but la perfection. Elle montre ce qui est déjà cassé, ce qui n'est que du bruit de style et ce qui bloquera tout le monde le premier jour.
Ensuite, choisissez comment vous voulez exécuter les hooks.
- Un framework pre-commit est plus simple à partager dans l'équipe et se comporte pareil sur la plupart des machines.
- Les hooks git natifs sont simples, mais ils sont locaux par défaut, donc les gens les oublient ou ne les installent jamais.
Pour la plupart des équipes, une configuration partagée dans le repo fonctionne le mieux car elle peut être revue comme n'importe quel autre changement.
Gardez la configuration ennuyeuse : un fichier, des noms clairs et seulement les vérifications que vous voulez réellement appliquer. Installez les hooks localement et confirmez qu'ils s'exécutent en faisant une petite modification et en la commitant.
Un déploiement qui évite le drame :
- Créez une branche baseline et lancez tous les hooks une fois pour enregistrer ce qui échoue.
- Ajoutez le fichier de config au repo et gardez le premier ensemble de hooks petit.
- Installez les hooks et vérifiez qu'ils s'exécutent sur un vrai commit.
- Commencez par n'exécuter que sur les fichiers modifiés (ou en mode avertissement), puis passez au blocage.
- Ajoutez un hook à la fois pour que les échecs restent faciles à comprendre.
L'application progressive compte. Si votre premier commit bloque sur 700 changements de formatage, les gens contourneront les hooks. Corrigez d'abord les problèmes à haut risque (secrets, erreurs de lint évidentes), puis revenez au formatage.
Ajouter un formatage qui stoppe les débats de style
Le formatage est le garde-fou le plus facile à ajouter, et il rapporte vite. Choisissez un formateur par langage et traitez-le comme la source de vérité unique. Une fois le style cohérent, les revues peuvent se concentrer sur la logique, pas sur les tabulations ou le type de guillemets.
Pour la vitesse, exécutez le formatage seulement sur les fichiers indexés. Cela garde les commits réactifs et évite le problème « j'ai touché une ligne et 2000 lignes ont changé ».
Une bonne baseline de formatage évite aussi les diffs bruyants qui font perdre du temps :
- Normaliser les fins de ligne (pour éviter les conflits Windows/macOS)
- Supprimer les espaces en fin de ligne
- S'assurer que les fichiers se terminent par une nouvelle ligne
- Garder l'encodage des fichiers cohérent (généralement UTF-8)
Faites attention aux fichiers générés et aux dossiers vendor. En général, vous ne voulez pas qu'un formateur réécrive des outputs de build, des lockfiles que vous ne gérez pas, ou du code tiers copié. Excluez-les explicitement pour que le formatage reste prévisible:
# Example idea (not a full config)
exclude: \"^(dist|build|vendor|\\.next|coverage)/\"
Enfin, mettez-vous d'accord sur le moment du formatage. Si vous formatez à l'enregistrement dans l'éditeur, le formatage au commit doit correspondre pour ne pas entrer en conflit. Une règle simple marche bien : formatez à la sauvegarde pour le confort quotidien, et appliquez le formatage au commit pour que le dépôt reste propre même quand quelqu'un utilise un autre éditeur.
Ajouter un linting qui attrape de vrais problèmes
Le linting est le plus utile dans les dépôts hérités lorsqu'il empêche de vrais bugs, pas quand il déclenche des débats sur des virgules. Avec des hooks pre-commit, l'objectif est simple : arrêter les erreurs évidentes avant qu'elles n'atterrissent dans une branche et ne gaspillent du temps en CI.
Choisissez un linter adapté à votre langage principal et configurez-le pour prioriser les signaux de bug plutôt que le style personnel. Les règles qui rapportent souvent vite incluent :
- Variables et imports inutilisés
- Gestion d'erreurs manquante (promesses non catchées, retours ignorés)
- Construction de chaînes dangereuse (source commune d'injections)
- Comparaisons suspectes et code inaccessible
- Erreurs de copier-coller et logique dupliquée
Si votre repo est typé, ajoutez une vérification de type légère là où elle aide. Ne commencez pas par vérifier tout l'univers. Ciblez les parties qui cassent le plus souvent en production (auth, paiements, accès aux données), puis étendez.
Le code legacy est la raison pour laquelle le linting échoue dans les projets hérités. Ne « réparez pas le monde » juste pour intégrer un garde-fou. Utilisez des ignores ciblés ou limitez le linting aux fichiers modifiés. Une autre option est une baseline temporaire pour que le hook ne bloque que les nouvelles violations, puis éliminez progressivement les vieux problèmes.
Rendez la sortie conviviale. Privilégiez des configs qui montrent une courte explication et une correction suggérée, et activez l'auto-fix là où c'est sûr.
Maintenez la prédictibilité d'exécution. Un hook qui prend parfois 5 secondes et parfois 2 minutes sera désactivé. Visez des vérifications cohérentes et rapides sur les fichiers indexés, puis laissez l'analyse plus lourde au CI.
Ajouter un scan de secrets avant que quoi que ce soit n'aille sur le remote
Les dépôts hérités cachent souvent des secrets en clair. Un scan rapide de secrets dans vos hooks pre-commit attrape les fuites évidentes (clés API, tokens d'accès, clés privées, secrets OAuth) avant qu'elles ne quittent un laptop.
Utilisez un scanner capable de détecter des motifs et de bloquer les nouvelles fuites. Beaucoup d'équipes choisissent des outils qui échouent le commit quand un nouveau secret est introduit, tout en permettant une baseline revue des résultats connus.
Rendez la règle simple : bloquer les commits qui ajoutent de nouveaux secrets. Si le hook se déclenche, le développeur supprime le secret ou le marque comme faux positif revu via un processus contrôlé (pas en désactivant le hook).
Pour les exceptions, privilégiez une allowlist explicite et facile à revoir. Gardez la baseline sous contrôle de version et considérez les changements comme significatifs.
Les secrets se glissent généralement par quelques endroits prévisibles :
- Fichiers .env et configs locales
- Fichiers d'exemple de settings
- Logs de debug et dumps d'erreur
- Fixtures de tests et réponses HTTP enregistrées
- Extraits copiés depuis des tableaux de bord fournisseurs
Si vous découvrez qu'un secret a déjà été commis, considérez-le comme compromis, même si le dépôt est privé :
- Faites tourner ou révoquez la clé/token
- Retirez-le du code et remplacez par une variable d'environnement
- Vérifiez l'historique git et purgez si nécessaire
- Cherchez où il a été utilisé (logs, déploiements, CI)
- Ajoutez un contrôle de régression pour qu'il ne puisse plus se produire
Ajouter des tests rapides que les développeurs exécuteront réellement
Les seuls tests utiles au moment du commit sont ceux que les gens ne sautent pas. Visez un petit ensemble fiable qui termine en moins de 60 secondes sur un portable normal. Si c'est plus long, les développeurs le contourneront et votre garde-fou deviendra du bruit.
Commencez par des smoke tests qui prouvent que le dépôt se construit encore et que les chemins les plus importants fonctionnent toujours. De bons candidats sont des tests qui détectent rapidement les cassures évidentes, pas la couverture complète.
Que lancer en pre-commit
Gardez ça court et lié aux échecs que vous avez réellement rencontrés :
- Vérification de build (compilation, typecheck ou bundle minimal)
- Sanity des migrations de DB (valider le schéma ou appliquer sur une DB jetable)
- Un ou deux tests d'appel API (endpoint de santé, flux core create-read)
- Smoke auth (connexion fonctionne, route protégée reste protégée)
- Un sous-ensemble minimal de tests unitaires tagués « smoke » ou « fast »
Faites en sorte que la commande fonctionne sur n'importe quelle machine avec un minimum de configuration. Préférez un point d'entrée unique (par exemple une tâche make ou un script npm) qui échoue avec une sortie claire. Évitez d'exiger des services spéciaux présents seulement sur la machine d'un développeur.
Où vont les tests plus lourds
Si une suite de tests prend des minutes, sortez-la du pre-commit :
- Pre-commit : smoke tests rapides seulement
- On push ou PR : tests unitaires et d'intégration complets
- Nightly : tests end-to-end lents, tests de charge, audits de dépendances
Pour garder les tests déterministes, réduisez les dépendances réseau instables. Simulez les APIs externes, figez le temps quand nécessaire et utilisez des fixtures locales. Si vous devez toucher un service, faites-le optionnel et skippez par défaut en pre-commit.
Exemple : stabiliser un repo prototype généré par IA
Imaginez un dépôt qui a commencé comme prototype rapide créé par un outil IA. Il démo bien, mais la production casse souvent. L'auth tourne parfois en boucle, les dossiers sont en pagaille et chaque changement risque d'ouvrir une nouvelle brèche.
C'est là que les hooks pre-commit brillent : ajoutez de petits garde-fous qui arrêtent les pires erreurs tôt, sans lancer une grosse refonte.
Un déroulé simple en trois commits maintient la confiance :
- Premier commit : ajoutez un formateur et un linter basique avec des defaults sûrs.
- Deuxième commit : ajoutez le scan de secrets, retirez soigneusement tout
.envcommis, remplacez-les par un fichier d'exemple et faites tourner les clés fuitées. - Troisième commit : ajoutez un smoke test qui reproduit la dernière panne (par exemple un flux d'auth qui doit produire une session valide).
Quand vous expliquez ces changements à un fondateur non technique ou un client, concentrez-vous sur les résultats :
- « Cela bloque les fuites accidentelles de mots de passe et de clés API avant que le code ne quitte un laptop. »
- « Cela attrape les erreurs évidentes avant qu'elles ne gaspillent du temps en CI ou lors du déploiement. »
- « Ce test rapide évite la panne spécifique pour laquelle vous venez de payer. »
- « Rien de tout cela ne change les fonctionnalités. Ça rend juste les changements futurs plus sûrs. »
Pièges courants et comment les éviter
Les dépôts hérités ont déjà assez de friction. La manière la plus rapide de faire échouer les hooks est de les faire paraître comme une punition. Les bons garde-fous sont discrets la plupart du temps, et bruyants seulement quand ils attrapent quelque chose qui vous aurait coûté du temps plus tard.
Gardez les hooks rapides et prévisibles
Le piège principal est de rendre les hooks si stricts que personne ne peut commit. Si ça prend plus d'une minute, les gens utiliseront des flags de contournement et cesseront de faire confiance à l'installation.
Règles pratiques :
- Exécutez seulement des vérifications rapides localement (format, lint, secrets et un petit smoke test).
- Ne lancez pas la suite complète de tests à chaque commit.
- Ne modifiez que les fichiers indexés. L'auto-fix des fichiers non indexés crée des diffs surprenants.
- Commencez par des avertissements pour les règles bruyantes, puis serrez la vis une fois le dépôt plus propre.
- Rendre la sortie claire : un message d'erreur doit dire quoi faire ensuite.
Si votre formateur ou linter touche régulièrement des fichiers qui n'ont pas fait partie du commit, passez en mode staged-only (ou utilisez un outil qui le supporte) pour que le hook n'édite jamais du travail en cours.
Faire du contournement un choix conscient
Un autre échec courant est de laisser les gens ignorer les échecs de hook sans plan. Parfois, contourner est valide (hotfix, outil upstream cassé, démo urgente), mais cela doit rester une exception délibérée.
Définissez les attentes dans le repo :
- Documentez quand le contournement est permis et quel suivi est requis.
- Si quelqu'un contourne, CI doit toujours attraper la même classe de problèmes.
Surveillez la parité CI. Si les développeurs utilisent une version de linter locale et que CI en utilise une autre, vous aurez des commits « ça marche sur ma machine ». Figez les versions des outils et gardez les hooks locaux alignés avec CI pour que les échecs soient cohérents.
Checklist rapide et prochaines étapes
Si vous ajoutez des hooks pre-commit à un dépôt hérité, gardez la première passe petite et fiable. Vous essayez d'attraper les problèmes évidents tôt, sans faire des commits une punition.
Une baseline que vous pouvez mettre en place en une après-midi :
- Auto-format au commit
- Lint seulement les fichiers que vous avez touchés (rapide, règles à fort signal)
- Scan de secrets (clés, tokens, clés privées, commits accidentels de .env)
- Exécuter une commande de test rapide (smoke test ou ensemble de tests unitaires ciblés)
- Figer les versions des outils
Déployez par étapes pour que l'équipe n'ait pas d'opposition :
- Baseline : exécuter les hooks seulement sur les fichiers nouveaux ou modifiés
- Avertir : faire échouer les hooks localement, mais ne pas bloquer CI immédiatement
- Imposer : bloquer les commits et faire échouer CI quand les hooks échouent
Après une semaine, vous devriez voir moins de commits « corriger le formatage », moins de commentaires de PR sur le style, moins d'échecs CI causés par des problèmes faciles à détecter, et des revues plus rapides parce que les gens se concentrent sur la logique au lieu du bruit.
Sachez quand arrêter de coller des rustines. Si chaque hook met au jour des problèmes profonds (tests instables, auth qui casse aléatoirement, configs qui fuient, modules emmêlés), les garde-fous ne répareront pas la fondation. C'est le moment d'un travail de réparation ciblé : restructurer, durcir la sécurité et arriver à un point où les tests rapides ont vraiment du sens.
Si le dépôt a commencé comme un prototype généré par IA et continue de casser en production, FixMyMess (fixmymess.ai) est conçu pour cette situation : diagnostiquer la base de code, réparer la logique et les problèmes de sécurité, et la préparer au déploiement. Un audit rapide peut aussi vous aider à décider quels garde-fous appliquer en premier pour ne pas ralentir l'équipe.
Questions Fréquentes
Pourquoi utiliser des hooks pre-commit si nous avons déjà CI ?
CI détecte des problèmes après que le mauvais commit a été partagé. Les hooks pre-commit arrêtent les erreurs les plus courantes avant qu'elles n'atteignent votre branche, vos coéquipiers ou votre pipeline, ce qui réduit les builds cassés et le temps perdu à relancer CI.
Quels sont les premiers garde-fous à ajouter à un dépôt hérité ?
Commencez petit : un formateur, un linter à fort signal, un scan de secrets et un test ou une vérification de types rapide. Cet ensemble évite les diffs bruyants, les bugs évidents, les identifiants divulgués et les régressions faciles sans transformer les commits en corvée lente.
À quelle vitesse doivent être les hooks pre-commit ?
Visez moins de 60 secondes sur un portable normal, et privilégiez les vérifications qui s'exécutent uniquement sur les fichiers indexés ou modifiés. Si les hooks sont lents ou imprévisibles, les gens les contourneront et vous perdrez tout le bénéfice.
Comment éviter un énorme diff « formater tout » ?
Formatez seulement ce que vous committez, pas tout le dépôt. Cela maintient les diffs petits, évite les modifications surprises dans des fichiers non liés et facilite l'intégration d'un garde-fou dans une base de code encombrée sans déclencher une guerre de style.
Comment appliquer le linting sans casser tout le dépôt ?
Exécutez un run de baseline pour voir ce qui échoue actuellement, puis configurez les hooks pour bloquer d'abord uniquement les nouvelles violations. Cela vous permet de continuer à livrer pendant que vous corrigez progressivement les problèmes hérités plutôt que d'essayer de tout réparer dans un PR douloureux.
Que faire lorsqu'un hook trouve un secret ?
Faites du scan de secrets un blocage ferme pour les nouvelles fuites, et considérez tout secret trouvé dans le code comme compromis. Retirez-le du code, révoquez ou faites tourner la clé, et gardez le scanner activé pour empêcher la même erreur de se reproduire.
Quels tests doivent être en pre-commit vs CI ?
Commencez par un simple smoke test reflétant des pannes réelles que vous avez vues (par exemple un flux d'authentification qui doit produire une session valide) ou une construction minimale qui doit réussir. Laissez les tests d'intégration et bout en bout plus lourds à CI pour que les commits locaux restent rapides et fiables.
Comment fonctionnent les hooks pre-commit dans un monorepo ?
Scoppez les vérifications aux dossiers que vous avez touchés pour que l'édition de l'API n'entraîne pas une build complète du front-end, et vice versa. Le comportement par défaut devrait être « exécuter ce qui a changé », sinon les monorepos rendent vite les hooks trop lents pour rester activés.
Quand est-il acceptable de contourner les hooks ?
Autorisez le contournement uniquement pour de véritables urgences, et faites-en un choix conscient avec un suivi clair. Même lorsqu'un développeur contourne localement, CI doit toujours exécuter les mêmes types de vérifications pour que les exceptions ne deviennent pas la norme.
Quand doit-on arrêter d'ajouter des garde-fous et demander de l'aide extérieure ?
Si chaque changement continue de casser l'auth, de divulguer des configs ou de révéler des problèmes structurels profonds, les hooks ne répareront pas les fondations : ils ne feront que montrer la douleur plus tôt. Si votre dépôt vient d'outils IA et doit être prêt pour la production, FixMyMess (fixmymess.ai) peut réaliser un audit gratuit du code, diagnostiquer, réparer la logique, renforcer la sécurité, refactorer et préparer le déploiement — la plupart des projets sont terminés en 48–72 heures.