Git Hook que es Desarrollo

Git Hooks: qué hay que saber para sacarles el máximo partido

14/03/23 10 min. de lectura

Hace apenas unos meses que estuvimos hablando de qué era Git, cómo aprender a sacarle el máximo partido, y cómo utilizarlo para el manejo de los repositorios y el control de las versiones en entornos colaborativos.

Hoy queremos ir un paso más allá y profundizar en los .git/hooks. Para ello, vamos a conocer qué son, para qué sirven y cómo utilizarlos para mejorar la calidad de nuestro código de manera automática. El objetivo es conseguir unificar los criterios de formato para que cuando trabajemos en colaboración con otros desarrolladores, podamos dedicar más tiempo a la lógica de nuestros desarrollos.

¿Qué son los .git/hooks y para qué sirven? 🤔

Los hooks son una característica intrínseca de Git.

Son scripts que Git ejecuta antes o después de ciertos eventos como commit, push o receive. Así, si por ejemplo ejecutamos un comando ‘git.commit’, lo que hará Git es buscar automáticamente si existe algún hook que coincida con este evento. Y si existe, lo ejecutará.

¿Cómo se agrupan los .git/hooks? 👇

Básicamente los hooks se agrupan en ejecución en dos partes.

Por parte del cliente, en el que encontramos tres tipos:

  • Committing-Workflow: pre-commit, prepare-commit-msg, commit-msg.
  • Email Workflow: applypatch-msg, pre-applypatch, post-applypatch.
  • Other: pre-rebase, post-rewrite, post-merge, pre-push, pre-auto-gc.

Por parte del servidor:

  • Server-side: pre-receive, update, post-receive.

¿Cómo funcionan los .git/hooks? 🙌

Cuando se inicializa un repositorio se crea de manera automática la carpeta .git/hooks con una serie de ejemplos. Es importante tener en cuenta que esta carpeta estará oculta.

Funcionamiento Git Hooks

Para que un hook sea ejecutable deberemos quitarle la extensión ‘.sample’. Por defecto, tienen el permiso de ejecución, siempre y cuando no lo hayamos creado de cero. En ese caso, habrá que asignarle dicho permiso:

$ chmod +x <nombre_hook>

Normalmente se utiliza bash, shell o Python para dichos scripts. Sin embargo nosotros podremos crearlos con el lenguaje que queramos. Eso sí, habrá que cumplir un único requisito: tendremos que indicar en la cabecera del script la ruta del interprete que vayamos a utilizar para que el sistema sepa cómo ejecutarlo:

  • #!/bin/sh
  • #!/usr/bin/env Python
  • #!/usr/bin/env ruby

Los hooks que comienzan por ‘pre-‘ se ejecutarán antes de dichas acciones, a diferencia de los que empiecen por ‘post-‘, que se ejecutarán después. Cada uno de ellos tiene un uso: el primero se puede utilizar para hacer ciertas comprobaciones antes de la acción; mientras que el segundo se emplea para realizar acciones posteriores tipo notificación, limpieza de directorios, etc.

¿Cuándo utilizar los .git/hooks? 👀

Partamos de la base de que las casuísticas pueden ser muy amplias. Por eso, por ahora, vamos a centrarnos en la parte relacionada con los ‘commit’ para que podamos estandarizar y automatizar el formateo de nuestro código. Esto, además, nos permitirá establecer ciertos requisitos antes de hacer un ‘commit’ de nuestros cambios.

Repasando los hooks relacionados con la acción de ‘commit’, nos podremos encontrar con los siguientes casos:

  • pre-commit.

Este hook se ejecutará siempre que se ejecute el comando ‘git commit’. Es el script ideal si lo que buscamos es ejecutar un test del código o aplicar ciertas reglas de estilo. Un código de salida distinto de cero abortará la operación.

*** Para este caso concreto, podemos utilizar un framework basado en Python ya existente: ‘pre-commit’. Este nos aportará muchas funcionalidades, a la vez que nos ahorrará mucho tiempo.

  • prepare-commit-msg.

Se ejecutará después del ‘pre-commit’ y es apropiado para establecer un mensaje de commit automático en base a la branch desde la cual se desarrolle. En este caso, un código de salida distinto de cero también abortará la operación.

  • commit-msg.

Se ejecutará después de que el usuario haya introducido un mensaje de ‘commit’. Lo que nos va a permitir es añadir un aviso en el caso de que el mensaje no se ajuste a los estándares establecidos. Al igual que en los casos anteriores, un código de salida distinto de cero abortará la operación.

  • post-commit.

Se ejecutará después de ‘commit-msg’ y su función principal es la de enviar notificaciones. En este caso, el código de salida no afecta al resultado.

*** El hecho de que las comprobaciones previas generen un código de error, se traduce en que ese ‘commit’ no se va a realizar, y por lo tanto se impedirá hasta que se cumpla la condición.

Ejemplo de uso: instalar framework de ‘pre-commit’

Como hemos comentado en el punto anterior, vamos a instalar el framework de ‘pre-commit’ mediante el gestor de paquetes.

Para ello seguiremos los siguientes pasos:

  • Ejecutaremos $ pip install pre-commit.
  • Tendremos que instalar el hook en nuestro repositorio mediante el comando $ pre-commit install.
  • Esto creará un nuevo hook llamado ‘pre-commit’ cuya función es ejecutar el fichero ‘.pre-commit-config.yaml’ de nuestra carpeta raíz. La siguiente imagen muestra el contenido de ese hook:
ejemplos de uso git hooks

El fichero YAML al cual hace referencia aún no existe, pero no hay ningún problema porque en el siguiente paso lo configuraremos.

Lo podemos generar como fichero vacío, por ejemplo mediante $ touch .pre-commit-config.yaml

  • A continuación podemos editarlo con el editor que más nos guste y rellenarlo con la información que queramos. La sintaxis deberá ser:

repos:

–   repo: <repo_url>

    rev: <version_number>

    hooks:

    –   id: <hook_id>

        name: <message information for hook>

        language: <language_used>

        entry: <input_value>

        args: <arguments or options to define the hook>

        stages: <stage_execution>

*** En este punto, hemos detallado las opciones más utilizadas para cada hook, pero existen más.

Siguiendo con este mismo ejemplo, vamos a empezar por los ‘pre-commit-hooks’ básicos. Comunes a muchos desarrollos, son los que realizan todo tipo de comprobaciones estándares como eliminar espacios en blanco, cambiar los finales de línea, comprobar la sintaxis de ficheros json/ yaml, o evitar hacer commit a ramas ‘master’ y ‘main’.

Una vez que lo hayamos hecho, el resultado final deberá ser algo similar a esto:

Gi hooks ejemplos de uso

Y ejecutando el commit el resultado será esto:

Un paso más allá 👟

Vamos a imaginarnos que formamos parte de un equipo de desarrolladores que presta unos servicios determinados a sus clientes. Y yendo más allá, supongamos que en ese equipo trabajamos mediante peticiones o incidencias abiertas a través de herramientas de ticketing.

En dicho supuesto resulta lógico pensar que queramos incluir de forma obligatoria una referencia al “CLIENT_ID-xxx” encargado de abrir nuestro ticket, así como el tipo de desarrollo (‘ref: ‘ o ‘bug: ‘). Esto lo que va a permitirnos es hacer, de una manera más sencilla, un seguimiento de las evoluciones del código y de su relación con las peticiones que nos puedan ir llegando.

Para ello, lo primero que tendríamos que hacer sería comprobar los mensajes de los ‘commits’ del equipo de desarrollo. Y ¿cómo podemos hacerlo? De una manera muy sencilla: mediante la opción ‘commit-msg’, puesto que este hook permite evaluar los mensajes de ‘commit’.

Para proceder a su instalación:

Ejecutamos $ pre-commit install –install-hook -t commit-msg.

Esto nos creará otro hook llamado ‘commit-msg’ (en la carpeta .ghit/hooks) con esta configuración:

commit msg

Como se puede ver, en este caso también hace referencia al mismo fichero de configuración YAML anterior.

El siguiente paso será añadir la información que necesitemos para ese nuevo hook en dicho fichero (.pre-commit-config.yaml). Al tratarse de un script, será un repo de tipo ‘local’ y lo haremos usando “language: pygrep”.

Esto lo que nos va a permitir es personalizar cómo se comprobará el mensaje ‘commit utilizado’. Por poner un ejemplo:

Como puede apreciarse, en este caso, usando expresiones regulares podemos comprobar el contenido del mensaje.

Si hacemos un ‘commit’ sin incluir la información requerida, el resultado sería algo similar a esto:

Git Hooks 3

Mientras que si lo hacemos cumpliendo todos los criterios requeridos, se validaría correctamente la expresión regex y por lo tanto pasaría la comprobación:

Un caso concreto: desarrollo con Terraform

Por último, vamos a suponer que estamos desarrollando con Terraform. En este caso, si lo que buscamos es realizar comprobaciones de nuestro código y una serie de comprobaciones adicionales como seguridad, formato, etc, podríamos utilizar un repo específico.

Para ello, usaremos uno ya creado.

Lo importaremos como ‘repo’ y añadiremos dichos hooks a nuestro fichero YAML de configuración. El resultado que deberíamos obtener debe ser algo similar a esto:

A continuación si realizamos un ‘commit’, las comprobaciones serían algo similar a lo que puedes ver en esta imagen:

Git Hooks 6

Como se aprecia, se muestra un mensaje de error. El motivo es que se declaró una variable sin identificar su tipo. Sin embargo, una vez corregido, pasará todos los test y realizará el commit.

Git Hooks

👁 Todo lo que hemos visto aquí es solo una pequeña muestra de las capacidades que tienen los hooks y de todo el provecho que podemos sacarles.

Por eso, desde Santander os animamos a seguir ahondando en la materia para conocerla mejor y aprovecharla para vuestro día a día. Porque los hooks pueden llegar a ser muy útiles, sobre todo si estamos hablando de grandes equipos encargados de grandes volúmenes de trabajo.


Santander Digital Services
 es una compañía del Grupo Santander con más de 7.000 empleados y basada en Madrid. Trabajamos para convertir al Santander en un banco digital con sucursales.

Mira las posiciones que tenemos abiertas aquí para unirte a este equipazo y Be Tech! with Santander 🚀

Síguenos en LinkedIn y en Instagram.

Javier Gomez

Javier Gómez

Santander Global T&O

Ingeniero de sistemas con más de 20 años de experiencia en diferentes roles como arquitecto de sistemas, gestionando soluciones de virtualización de Apps & VDIs y proporcionando soluciones end-to-end, así como administrando sistemas y automatizando tareas mediante PowerShell.

Me considero una persona inquieta y un infatigable explorador del universo IT, que ha sabido hacer de su trabajo su pasión.

 

👉Mi perfil de LinkedIn

 

Otros posts