Un historial con mensajes como "cambios", "arreglos" o "ahora sí" no sirve para nada cuando necesitas encontrar qué commit rompió producción. La convención Conventional Commits resuelve esto con un formato simple:
tipo(alcance opcional): descripción Por ejemplo: feat(auth): agregar login con Google o fix: corregir cálculo de impuestos. Además de ordenar el historial, permite generar changelogs y versiones semánticas de forma automática.
La forma más directa de exigirlo es un hook commit-msg: un script que git ejecuta justo después de que escribes el mensaje y que puede rechazar el commit. Lo vamos a hacer en bash puro, sin Node ni Python.
1. El hook
Crea una carpeta .githooks/ en tu repo y dentro un archivo commit-msg:
#!/usr/bin/env bash set -euo pipefail TIPOS="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert" MAX_LARGO=72 # Git pasa como $1 la ruta del archivo con el mensaje. encabezado="$(grep -v '^#' "$1" | sed '/^[[:space:]]*$/d' | head -n 1 || true)" # Deja pasar los mensajes que genera git (merge, fixup...). if [[ "$encabezado" =~ ^(Merge|Revert\ \"|fixup!|squash!) ]]; then exit 0 fi patron="^(${TIPOS})(\([a-z0-9._/-]+\))?!?: [^[:space:]].*$" if [[ ! "$encabezado" =~ $patron ]]; then echo "✖ Formato esperado: tipo(alcance): descripción" >&2 echo " Tipos: ${TIPOS//|/, }" >&2 exit 1 fi if (( ${#encabezado} > MAX_LARGO )); then echo "✖ Encabezado de ${#encabezado} caracteres (máx. ${MAX_LARGO})." >&2 exit 1 fi 2. Cómo funciona
-
$1: git no te pasa el mensaje, sino la ruta a un archivo temporal que lo contiene. Por eso leemos el archivo. -
grep -v '^#': cuando usas el editor, git agrega líneas de ayuda que empiezan con#. Las quitamos, junto con las líneas vacías, y nos quedamos con la primera: el encabezado. - El patrón:
(\([a-z0-9._/-]+\))?hace opcional el alcance,!?permite marcar cambios incompatibles (feat!: ...) y: [^[:space:]]exige un espacio después de los dos puntos y una descripción real. -
=~sin comillas en el patrón: en bash, si pones comillas a la derecha de=~, se compara como texto literal y no como expresión regular. Por eso el patrón vive en una variable. - Código de salida: si el hook termina con algo distinto de 0, git cancela el commit.
3. Activarlo para todo el equipo
En lugar de copiar el script a .git/hooks/ (que no se versiona), dile a git que use tu carpeta:
chmod +x .githooks/commit-msg git config core.hooksPath .githooks git add .githooks && git commit -m "chore: agregar hook commit-msg" Cada persona del equipo solo ejecuta git config core.hooksPath .githooks una vez después de clonar.
4. Probarlo
git commit --allow-empty -m "cambios varios" # rechazado git commit --allow-empty -m "feat: agregar buscador" # aceptado Si alguna vez necesitas saltarlo, existe git commit --no-verify, pero úsalo con moderación: el hook está ahí para cuidarte.
¿Te sirvió? Este ejemplo es parte del Pack Git Hooks y Pre-commit: paga lo que quieras, desde 1 USD. Más recursos gratis en GitHub.