También disponible en: English · Português · Français · العربية
Git hooks: la lista completa y cuáles pueden pararte
El conjunto completo que documenta git, y la respuesta medida a lo único que importa: ¿puede este hook detener lo que estás haciendo?
¿Qué es un hook de git?
Un hook de git es un archivo ejecutable dentro del directorio de hooks de tu repositorio, con el nombre de un momento de la vida de git. Cuando llega ese momento —vas a hacer un commit, acabas de fusionar, un push ha llegado al servidor— git ejecuta el archivo. Así impone un proyecto un formato de mensaje de commit, pasa un linter antes de que el código entre o rechaza un push forzado a la rama principal.
Git documenta 28. La mayoría de la gente se cruza con tres o cuatro. El resto cubre la aplicación de parches por correo, el rebase, el extremo receptor de un push, la recolección de basura y un puente a Perforce, y varios se ejecutan en sitios que jamás adivinarías por el nombre.
La pregunta con la que llega cualquiera es simple: si este hook falla, ¿me para? Todas las referencias que hemos encontrado responden copiando la lista del manual de git. Esta página responde ejecutándolos.
Cómo usarla
- Escribe el nombre de un hook. Obtienes dónde se ejecuta, qué dice la documentación de git sobre su estado de salida y qué pasó cuando se instaló de verdad y se le hizo fallar.
- O busca en todo el conjunto. La tabla de abajo tiene los 28. Buscar un comando de git —commit, push, git am— devuelve todos los hooks que se disparan durante él.
- Lee las dos columnas una contra otra. Vienen de sitios distintos, así que donde coinciden puedes fiarte de la respuesta, y donde la documentación no tiene palabra para lo que ocurre, la medición aporta una.
Qué pasó al ejecutarlos
Cada hook se instaló por su cuenta, en un repositorio desechable con un remoto bare local al lado, con un cuerpo que no hacía más que fallar. Después se realizó la operación a la que ese hook pertenece y se anotaron dos cosas: el código de salida que devolvió el comando y si el estado del repositorio se movió de verdad. Diecinueve de los 28 se pueden disparar así; el resto necesitan un depósito de Perforce, un transporte de correo, watchman o el protocolo de push más nuevo, y se dejan en blanco en vez de adivinarlos.
Cada caso se ejecutó además sin ningún hook instalado, y ese control tenía que salir bien y mover el estado antes de que la medición contara para nada. No es ceremonia. La primera versión de este experimento informó de que el hook pre-rebase no puede detener un rebase, lo cual es falso y pasó porque la rama que construía no tenía nada que rebasear, así que la operación no hacía nada hubiera hook o no. El control convirtió una falsedad publicable y plausible en un fallo ruidoso.
De los diecinueve: once detuvieron la operación, siete no cambiaron absolutamente nada y uno hizo algo para lo que no hay palabra corriente.
El hook que falla sin fallar
El hook post-checkout no puede detener un checkout. La propia documentación de git dice que no puede afectar al resultado, salvo en que el estado de salida del hook pasa a ser el estado de salida del comando. Medido, es exactamente lo que ocurre: el checkout se completa, estás en la rama nueva y git devuelve 1.
Así que un script escrito como un checkout seguido de un comando encadenado, que es como se escriben casi todos los scripts de despliegue y los pasos de CI, se para en seco en un repositorio cuyo hook post-checkout falla. El checkout funcionó. El comando falló. Son hechos distintos y solo uno de los dos es visible para el shell.
Merece la pena conocer otro código de salida. Cuando el hook reference-transaction rechaza en su estado prepared, git no devuelve un fallo normal: devuelve 128, su código para un error fatal. Cualquier cosa que compare códigos de salida debería esperarlo en vez de un 1.
El nombre no es la regla
Todo el mundo lo aprende así: los hooks que empiezan por pre- pueden bloquear, los que empiezan por post- no. La mitad es cierta. Nada llamado post- detuvo nada, y todos los hooks que no cambiaron absolutamente nada se llamaban post-algo.
La otra mitad falla. Solo 6 de los 11 hooks que detuvieron una operación se llaman pre-algo. Los otros cinco son applypatch-msg, commit-msg, prepare-commit-msg, update y reference-transaction, así que casi la mitad de lo que puede pararte no lo avisa en su nombre. prepare-commit-msg es la trampa dentro de la trampa: empieza por las letras p-r-e, no es un hook pre- y bloquea.
La regla de verdad es si git consulta el estado de salida en el punto donde se ejecuta el hook, que es una propiedad de la operación y no del nombre. Por eso update detiene un push, por eso reference-transaction puede impedir que se cree una rama y por eso post-checkout puede hacer fallar un comando sin cambiar nada.
Lo que esta página no puede decirte
Es una versión de git en una plataforma. La medición se tomó con la versión de git que aparece junto a las cifras, en Windows, y aunque la semántica de los hooks cambia despacio, cambia. Donde la documentación y la medición coinciden —que es en todo lo que se solapan— la respuesta es tan sólida como se puede sin leer el código fuente.
Nueve hooks no se midieron, y así lo dice su fila en vez de rellenarla. Uno de ellos, pre-auto-gc, se intentó y se abandonó: la recolección automática de basura solo se ejecuta cuando git decide que un repositorio tiene bastantes objetos sueltos, y esa decisión muestrea un directorio en vez de contar, así que ningún repositorio de prueba lo bastante pequeño la disparaba. Una fila cuyo control no puede hacerse honesto se deja fuera.
Por último, esto va de si un hook puede detener una operación, no de si debería. Un hook que rechaza trabajo solo sirve si la persona a la que para puede saber por qué, y git no imprime nada en tu nombre: lo que tu hook escriba en la salida de error es el mensaje entero que verá cualquiera.
¿Por qué es gratis?
La lista entera son un par de kilobytes que viajan con la página y se buscan en tu navegador. Nada de lo que escribes se sube, no se registra nada y no hay cuenta que crear.
Sin registro, sin límites y sin marca de agua en nada de lo que copies.