Aussi disponible en : English · Español · Português · العربية
Hooks git : la liste complète et ceux qui peuvent vous bloquer
L'ensemble complet que git documente, et la réponse mesurée à la seule question qui compte : ce hook peut-il arrêter ce que vous êtes en train de faire ?
Qu'est-ce qu'un hook git ?
Un hook git est un fichier exécutable placé dans le répertoire des hooks de votre dépôt et nommé d'après un moment de la vie de git. Quand ce moment arrive — vous allez valider, vous venez de fusionner, un push est arrivé sur le serveur — git exécute le fichier. C'est ainsi qu'un projet impose un format de message de commit, passe un linter avant que du code n'entre, ou refuse un push forcé sur la branche principale.
Git en documente 28. La plupart des gens en croisent trois ou quatre. Le reste couvre l'application de correctifs par courriel, le rebasage, le côté qui reçoit un push, le ramasse-miettes et une passerelle vers Perforce, et plusieurs s'exécutent à des endroits que leur nom ne laisse pas deviner.
La question avec laquelle on arrive est simple : si ce hook échoue, est-ce qu'il m'arrête ? Toutes les références que nous avons trouvées répondent en recopiant la liste du manuel de git. Cette page répond en les exécutant.
Comment l'utiliser
- Tapez le nom d'un hook et vous obtenez où il s'exécute, ce que la documentation de git dit de son code de sortie, et ce qui s'est passé quand il a réellement été installé et mis en échec.
- Ou fouillez l'ensemble dans le tableau ci-dessous, qui contient les 28. Chercher une commande git — commit, push, git am — ramène tous les hooks qui se déclenchent pendant elle.
- Lisez les deux colonnes l'une contre l'autre : elles viennent d'endroits différents, donc là où elles concordent la réponse est sûre, et là où la documentation n'a pas de mot pour ce qui se produit, la mesure en fournit un.
Ce qui s'est passé quand nous les avons exécutés
Chaque hook a été installé seul, dans un dépôt jetable flanqué d'un dépôt nu local, avec un corps qui ne faisait rien d'autre qu'échouer. Puis l'opération à laquelle ce hook appartient a été effectuée, et deux choses ont été relevées : le code de sortie renvoyé par la commande, et si l'état du dépôt avait réellement bougé. Dix-neuf des 28 se pilotent ainsi ; les autres réclament un dépôt Perforce, un transport de courrier, watchman ou le protocole de push le plus récent, et restent vides plutôt que devinés.
Chaque cas a également tourné sans aucun hook installé, et ce témoin devait réussir et faire bouger l'état avant que la mesure compte. Ce n'est pas une formalité. La première version de cette expérience concluait que le hook pre-rebase ne peut pas arrêter un rebasage — c'est faux, et cela venait de ce que la branche construite n'avait rien à rebaser, donc l'opération ne faisait rien, hook ou pas. Le témoin a transformé une contrevérité plausible et publiable en un échec bruyant.
Sur ces dix-neuf : onze ont arrêté l'opération, sept n'ont absolument rien changé, et un a fait quelque chose pour quoi il n'existe pas de mot courant.
Le hook qui échoue sans faire échouer
Le hook post-checkout ne peut pas arrêter un changement de branche. La documentation de git le dit elle-même : il ne peut pas influer sur le résultat, sinon que le code de sortie du hook devient celui de la commande. Mesuré, c'est exactement ce qui arrive : le basculement s'accomplit, vous êtes sur la nouvelle branche, et git renvoie 1.
Un script écrit comme un checkout suivi d'une commande enchaînée — c'est-à-dire la quasi-totalité des scripts de déploiement et des étapes d'intégration continue — s'arrête net sur un dépôt dont le hook post-checkout échoue. Le checkout a marché. La commande a échoué. Ce sont deux faits distincts et un seul est visible depuis le shell.
Un autre code de sortie mérite d'être connu. Quand le hook reference-transaction refuse dans son état prepared, git ne renvoie pas un échec ordinaire : il renvoie 128, son code d'erreur fatale. Tout ce qui compare des codes de sortie doit s'y attendre plutôt qu'à un 1.
Le nom n'est pas la règle
Tout le monde l'apprend ainsi : les hooks commençant par pre- peuvent bloquer, ceux commençant par post- non. La moitié est vraie. Rien de nommé post- n'a arrêté quoi que ce soit, et tous les hooks qui n'ont absolument rien changé portaient un nom en post-.
L'autre moitié tombe. Six seulement des 11 hooks ayant arrêté une opération s'appellent pre-quelque-chose. Les cinq autres sont applypatch-msg, commit-msg, prepare-commit-msg, update et reference-transaction : près de la moitié de ce qui peut vous arrêter ne l'annonce pas dans son nom. prepare-commit-msg est le piège dans le piège — il commence par les lettres p-r-e, n'est pas un hook pre-, et bloque.
La vraie règle tient à ce que git consulte ou non le code de sortie à l'endroit où le hook s'exécute, ce qui est une propriété de l'opération et non du nom. C'est pourquoi update arrête un push, pourquoi reference-transaction peut empêcher la création d'une branche, et pourquoi post-checkout peut faire échouer une commande sans rien changer.
Ce que cette page ne peut pas vous dire
C'est une version de git sur une plateforme. La mesure a été prise avec la version de git affichée à côté des chiffres, sous Windows, et si la sémantique des hooks bouge lentement, elle bouge. Là où la documentation et la mesure concordent — c'est-à-dire partout où elles se recoupent — la réponse est aussi solide que possible sans lire le code source.
Neuf hooks n'ont pas été mesurés, et leur ligne le dit au lieu d'être remplie. L'un d'eux, pre-auto-gc, a été tenté puis abandonné : le ramasse-miettes automatique ne se déclenche qu'une fois que git juge qu'un dépôt compte assez d'objets isolés, et cette décision échantillonne un répertoire au lieu de compter, si bien qu'aucun dépôt de test assez petit ne la déclenchait. Une ligne dont le témoin ne peut pas être rendu honnête est laissée de côté.
Enfin, il s'agit de savoir si un hook peut arrêter une opération, pas s'il le devrait. Un hook qui refuse du travail n'est utile que si la personne arrêtée peut savoir pourquoi, et git n'imprime rien à votre place : ce que votre hook écrit sur la sortie d'erreur constitue l'intégralité du message que verra quiconque.
Pourquoi est-ce gratuit ?
La liste entière tient en quelques kilo-octets livrés avec la page et consultés dans votre navigateur. Rien de ce que vous tapez n'est envoyé, rien n'est journalisé, et il n'y a aucun compte à créer.
Sans inscription, sans limite, et sans filigrane sur ce que vous copiez.