A la hora de llevar un commit al repositorio necesitamos cumplir unas normas para explicar el contenido de esas modificaciones de una forma clara y concisa para que cualquier persona (o bot) al ver un histórico de los cambios ya sea en el historial de git, o en algún archivo changelog pueda visualizar la motivación sin entrar al detalle de las mismas e incluso hacer un versionado.

Por lo tanto ese commit ha de tener un hecho único con un alcance (aunque contenga varios archivos). Esto significa que no se deberían juntar modificaciones en un mismo commit que no tienen nada que ver entre ellas (otra cosa es que en luego se realice algun «squash commit» al hacer un «merge«). Por ejemplo si hemos hecho una calculadora que suma y resta no se debería poner todo bajo un único commit con el texto: «calcula operaciones de suma y resta», lo ideal sería hacer dos commits, uno con la suma y otro con la resta. De esta manera incluso podemos borrar sólo la operación de suma (borrar commit de suma) o movernos en el tiempo hasta el commit de la operación resta llegado el momento.

Estructura del commit

Hemos hablado de un texto o frase en el commit que sería el título, pero este tiene más apartados donde se puede almacenar más información, dicha estructura es la siguiente:

  1. Título: Siendo obligatoria, es la parte más importante e incluso debería cumplir algunas reglas como «Conventional Commits» o «Angular Commit Format» por dar unos ejemplos sin sobrepasar los 100 caracteres. Esta parte se dividiría a su vez en <Tipo>[Scope optativo]: <Descripción o asunto>
  2. Cuerpo: Optativa. Explicación más extensa como señalar qué se ha hecho.
  3. Pie: Optativa. Debe contener solo referencias a issues, backlog items, … u otro tipo de tiquet.

Así a modo de la estructura que se enviaría tendría el siguiente aspecto:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

Hay cientos de artículos al respecto donde puedes extraer más información sobre las buenas prácticas a la hora de escribir los mensajes: tipos de modificaciones, scopes (o ámbitos), verbos, escribirlo en inglés, etc.

Validación del mensaje con commitlint

Antes de continuar hay que tener instalado y configurado Husky además de conocer un poco el tema de git hooks. Para ello te recomiendo que leas el artículo Husky: mejora tus commits.

Commitlint

Commitlint herramienta para la validación del mensaje que se ejecutará en el git hook «commit-msg«.

Instalación

Basta con ejecutar el siguiente comando instalándose en las dependencias de desarrollo:

npm install --save-dev @commitlint/cli @commitlint/config-conventional

Si deseamos validar que el «scope» (que es optativo) pertenezca al nombre de una librería del monorepo nx, añadiremos a la instalación el package «@commitlint/config-nx-scopes».

Configuración

Inicializamos commitlint con su archivo de configuración llamado «commitlint.config.js» ubicado en la raíz del proyecto (a nivel del «package.json») con el siguiente contenido (un contenido muy simple):

module.exports = {
    extends: ['@commitlint/config-conventional', '@commitlint/config-nx-scopes']
}

Nota: añadimos la validación de los scopes de nx si también lo hemos instalado.

Para más información sobre mejorar la configuración la tienes aquí. Cabe destacar que este archivo se puede personalizar para validar mejor por ejemplo los scopes de nx, es decir, que no solo valide los nombres de librerías, si no también que incluya más scopes.

Git Hook commit-msg

Ahora creamos el archivo «commit-msg» en el directorio de Husky de la siguiente manera:

echo 'npx --no -- commitlint --edit ${1}' > .husky/commit-msg

Si resulta que el código está en una subcarpeta llamada por ejemplo «proyecto», entonces hay que indicar previamente que haga un cambio de directorio «cd ./proyecto» quedando el archivo:

cd ./proyecto
npx --no -- commitlint --edit ${1}

Extensión «Conventional Commits»

Aunque tengamos configurado la validación de los mensajes, siempre puedes crear de forma guiada el mensaje. Para esto te recomiendo que te instales en tu editor algún plugin o extensión para este proceso. En el caso de usar VS Code, puedes instalarte la extensión «Conventional Commits» que te ayudará a generarlos bien de inicio. Esto no quita que se siga validando el mensaje con commitlint.

Emojis en mensajes con devmoji

A veces solemos poner el código de un emoji (shortcode) en un mensaje para indicar de forma visual (en forma de icono) de qué se trata, por ejemplo escribiendo :heavy_plus_sign: aparecería un icono en forma de «+» (transforma de formato shortcode a formato unicode) indicando que se ha añadido una dependencia (puedes ver todos los emojis en https://gitmoji.dev/) pero según el «lector» que utilicemos veremos el texto en vez del icono. Para que se vea el icono para practicamente cualquier «lector», utilizaremos la librería devmoji (aunque ya lleva bastante tiempo sin actualizarse).

Instalación

Ejecutamos el siguiente comando:

npm install --save-dev devmoji

Ya tenemos instalada la librería en nuestro apartado de dependencias de desarrollo.

Git Hook prepare-commit-msg

Ahora creamos el archivo «prepare-commit-msg» en el directorio de husky de la siguiente manera:

echo 'npx --no -- devmoji --edit' > .husky/prepare-commit-msg

Como en el caso anterior si el código está en una subcarpeta llamada «proyecto», entonces hay que indicar previamente que haga un cambio de directorio «cd ./proyecto» quedando:

cd ./proyecto
npx --no -- devmoji --edit

Resumen

Hemos visto el proceso de validación del mensaje de commit mediante el package «@commitlint» haciendo uso de los git hooks (commit-msg y prepare-commit-msg) con Husky, así como la traducción de emojis de shortcode a unicode, incluyendo la instalación de una extensión de VS Code para facilitar su escritura.
Espero que con esto puedas mejorar el proceso de commits en tu día a día. Como siempre tienes el ejemplo en el repositorio de github de angularfrontenders.com.