El mensaje en los commits importa?

En el post anterior hablé un poco sobre la importancia de los hooks y explique cómo funcionaban,  me enfoque en herramientas linters de código donde se validaba el formato de cumplimientobasado en diferentes estandares, en este artículo hablaré del hook llamado commit-msg y me enfocare en la validación del mensaje usando dos herramientas muy interesantes que conocí en un proyecto por Carlos estas se agregan en el commit, como se aprecia en la Figura 1

Figura 1: Validación del mensaje del commit utilizando el hook commit-msg

Una de las mayores ventajas de los proyectos open source es su track de seguimiento de cambios el cual nos ha permitido ver cómo se trabaja en proyectos en donde se puede aportar libremente y gracias a ello tenemos referencias, unas pueden ser buenas y algunas no tanto de commits realizados en diferentes proyectos Ver Figura 2

Figura 2: Commits en un proyecto sacado de https://xkcd.com/1296/

En los siguientes repositorios públicos veremos algunos ejemplos de unos commits que siguen un estándar, algunos referenciados dentro de la propia comunidad y cultura de cómo se debe contribuir

Mypy

Consola

Figura 3: Commits vistos desde consola del proyecto mypy

Github

Figura 4: Commits vistos desde github del proyecto mypy

Uvloop

Consola

Figura 5: Commits vistos desde consola en una linea del proyecto uvloop

Github

Figura 6: Commits vistos desde github del proyecto uvloop

En los anteriores ejemplos se pudo observar unos commits escritos de una manera concisa, limpia y que además logra comunicar, lo cual es un punto importante en este artículo un poco viejo que me encontre por ahi donde se menciona que un commit finalmente comunica el porqué del cambio, se puede también hacer referencia a este artículo  en donde se especifica que debe tener un buen commit, entre ellos es buena practica  encapsular  en un formato subject y body con máximo 50 a 72 caracteres respectivamente como se aprecia en la Figura 7

Figura 7: Estructura de un commit en el proyecto FastAPI 

Ahora no todos los commits necesitan tener necesariamente un body, con un simple subject descriptivo podría bastar en este caso podría verse la Figura 8

Figura 8 : Commit obtenido de https://github.com/expressjs/express/commit/65aff94ec62b9f550aa7fb82cd8a1dd7b7da0bfc

Al final del dia creo que es importante entender que para que un commit sea un buen commit aparte de las reglas que ya se conocen de que sea atómico de que no dañe mas de lo que arregle, debe además tener un buen mensaje, dicho esto para facilitar el cumplimiento de esta tarea pasaremos a ver algunas herramientas y un ejemplo de cómo implementarlas

Herramientas

Para este ejemplo utilizaremos la herramienta husky y commitlint desarrolladas para trabajar en proyectos de javascript

Husky

Esta tool facilitara la gestión y el trabajo de los git hooks, en su documentación se describen así mismos como "Modern native Git hooks made easy" ya que como mencione en mi articulo anterior estos git hooks son scripts y esta herramienta evitara que se escriban de manera manual, ademas soporta todos los hooks disponibles

Commitlint

Es una tool que automatiza el cumplimiento del conventionalcommits, permitiendo agregar configuraciones y personalizaciones modificando a si un set de reglas que se van a validar

Ejemplo

Descritas las herramientas podemos pasar un poco al código, para ello voy primero a inicializar un repositorio vacío

git init

seguidamente voy a iniciar un proyecto

npm init

ahora instalare la herramienta commitlint

npm install -g @commitlint/cli @commitlint/config-conventional

commitlint necesita de una rchivo de entrada para configurar sus parámetros para ello creare el archivo llamado commitlint.config.js y dejare los parámetros de validación por defecto

module.exports = { extends: ["@commitlint/config-conventional"] };

ahora instalare husky

npm install husky --save-dev

después de instalado husky debe habilitarse, para ello se ejecuta el siguiente comando

npx husky install

al ejecutarse se agrega el script prepare, el package.json debe quedar de la siguiente forma

{
  "name": "myproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "prepare": "husky install"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@commitlint/config-conventional": "^12.1.4",
    "husky": "^6.0.0"
  }
}

al tener la herramienta instalada pasaré a crear el hook, como se mencionó anteriormente la herramienta husky soporta todos los hooks en este caso usare el hook commit-msg para ello ejecutare el siguiente comando

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

este comando creará el script correspondiente dentro de la carpeta ./husky, ahora agregare algunos cambios con git add agregando a staging

Figura 9: Cambios agregados a staging

y primero ejecutare un commit con un mensaje que no cumple el estándar para validar ejecuto el comando

git commit -m "test"

y vemos la siguiente salida en consola

Figura 10: Error generado por commitlint al no cumplir el estándar del mensaje

ahora commitiamos con un mensaje que si cumple el estándar

git commit -m "feat: added initial project configuration files"

al  usar este mensaje el commit es agregado sin problema, el estándar de los mensajes y su significado lo pueden encontrar aquí, igualmente el commitlint es totalmente personalizable para ver las reglas que se deben cumplir a continuación un ejemplo de los parámetros configurables

module.exports = {
	parserPreset: 'conventional-changelog-conventionalcommits',
	rules: {
		'body-leading-blank': [1, 'always'],
		'body-max-line-length': [2, 'always', 100],
		'footer-leading-blank': [1, 'always'],
		'footer-max-line-length': [2, 'always', 100],
		'header-max-length': [2, 'always', 100],
		'scope-case': [2, 'always', 'lower-case'],
		'subject-case': [
			2,
			'never',
			['sentence-case', 'start-case', 'pascal-case', 'upper-case'],
		],
		'subject-empty': [2, 'never'],
		'subject-full-stop': [2, 'never', '.'],
		'type-case': [2, 'always', 'lower-case'],
		'type-empty': [2, 'never'],
		'type-enum': [
			2,
			'always',
			[
				'build',
				'chore',
				'ci',
				'docs',
				'feat',
				'fix',
				'perf',
				'refactor',
				'revert',
				'style',
				'test',
			],
		],
	},
};

si por alguna razón se desea saltar la validación de los hooks se puede realizar utilizando el siguiente comando

git commit --no-verify

Un tip para finalizar, es que posiblemente si tiene una versión algo antigua de git puede que no les funcione debidamente las herramientas por eso recomiendo actualizarla a la última versión

Conclusiones

Al igual que el pensamiento de "clean code" debemos enfocarnos en "clean commits" para escribir mensajes en los commits que cumplan su función de brindar una trazabilidad y contexto, esto tiene mucha importancia en los proyectos open source incluso muchos en su reglas para contribuir dejan bastante claro la importancia de los mensajes, esto para mi debe adaptarse en los proyectos internos de las empresas ya que es una excelente práctica