¿Qué hace Commits Convencionales?
Redacta mensajes de commit siguiendo la especificación Commits Convencionales v1.0.0 para un historial de commits estructurado, generación automatizada de changelogs y versionado semántico.
Cuándo Usar Esta Habilidad
Usa esta habilidad cuando:
- Creando mensajes de commit para proyectos estructurados
- Validando el formato de mensajes de commit contra la especificación de Commits Convencionales
- Configurando la validación de mensajes de commit con commitlint
- Configurando la generación de changelogs desde el historial de commits
- Implementando automatización de versionado semántico
- Revisando mensajes de commit para verificar el cumplimiento de la especificación
- Capacitando equipos en estándares de mensajes de commit
- Integrando con herramientas como semantic-release, commitizen o git-cliff
Estructura del Mensaje
<tipo>[ámbito opcional]: <descripción>
[cuerpo opcional]
[pie(s) opcional(es)]
Componentes
| Componente | Requerido | Descripción | Ejemplo |
|---|---|---|---|
| tipo | Sí | Categoría del commit | feat, fix, docs |
| ámbito | No | Sección del código afectada | (auth), (parser) |
| descripción | Sí | Resumen breve de los cambios | añadir autenticación de usuario |
| cuerpo | No | Explicación detallada | Varios párrafos con contexto |
| pie | No | Cambios disruptivos, refs de issues | BREAKING CHANGE:, Refs: #123 |
Tipos de Commit
Tipos Requeridos (Impacto SemVer)
Estos tipos son obligatorios según la especificación de Commits Convencionales y afectan directamente al versionado semántico:
flowchart LR
Fix[fix: Corrección de errores<br/>para usuarios] --> PatchVer[PATCH<br/>0.0.X]
Feat[feat: Nueva funcionalidad<br/>para usuarios] --> MinorVer[MINOR<br/>0.X.0]
Breaking[Cualquier tipo con<br/>BREAKING CHANGE o !] --> MajorVer[MAJOR<br/>X.0.0]
style PatchVer fill:#e1f5ff
style MinorVer fill:#fff4e1
style MajorVer fill:#ffe1e1
| Tipo | Descripción | SemVer | Ejemplo |
|---|---|---|---|
feat | Nueva funcionalidad para usuarios | MINOR (0.X.0) | feat: añadir autenticación de usuario |
fix | Corrección de errores para usuarios | PATCH (0.0.X) | fix: evitar fallo en entrada vacía |
Tipos Recomendados (Convención Angular)
Estos tipos provienen de @commitlint/config-conventional basados en las guías de commit de Angular. No tienen un efecto SemVer implícito a menos que incluyan BREAKING CHANGE.
| Tipo | Descripción | Ejemplo |
|---|---|---|
build | Cambios en el sistema de compilación o dependencias externas | build: actualizar webpack a v5 |
ci | Cambios en la configuración de CI | ci: añadir Node 18 a la matriz de pruebas |
docs | Cambios solo de documentación | docs: actualizar referencia de API |
perf | Mejora de rendimiento | perf: reducir el tamaño del bundle en un 20% |
refactor | Cambio de código sin corrección de errores ni nueva funcionalidad | refactor: extraer lógica de validación |
style | Cambios de estilo de código (espacios, formato) | style: corregir sangría |
test | Añadir o corregir pruebas | test: añadir pruebas unitarias para el parser |
Tipos Comunes Adicionales
| Tipo | Descripción | Ejemplo |
|---|---|---|
chore | Cambios que no modifican archivos src o test | chore: actualizar .gitignore |
revert | Revierte un commit anterior | revert: feat: añadir autenticación de usuario |
Nota: Los equipos pueden definir tipos personalizados más allá de feat y fix, pero los tipos de la convención Angular son ampliamente compatibles con las herramientas.
Reglas de la Especificación
Las siguientes reglas constituyen la especificación oficial de Commits Convencionales 1.0.0 según RFC 2119.
Tipo y Ámbito
-
Los commits DEBEN tener un prefijo de tipo, que consiste en un sustantivo (
feat,fix, etc.), seguido por un ámbito OPCIONAL,!OPCIONAL, y dos puntos y espacio REQUERIDOS al final. -
El tipo
featDEBE usarse cuando un commit añade una nueva funcionalidad. -
El tipo
fixDEBE usarse cuando un commit representa una corrección de errores. -
Se PUEDE proporcionar un ámbito después de un tipo. Un ámbito DEBE consistir en un sustantivo que describa una sección del código, encerrado entre paréntesis, por ejemplo,
fix(parser):. -
Una descripción DEBE seguir inmediatamente después de los dos puntos y el espacio después del prefijo tipo/ámbito. La descripción es un resumen breve de los cambios de código, por ejemplo,
fix: problema de análisis de array cuando había múltiples espacios en string.
Cuerpo
-
Se PUEDE proporcionar un cuerpo de commit más largo después de la descripción breve, proporcionando información contextual adicional. El cuerpo DEBE comenzar una línea en blanco después de la descripción.
-
Un cuerpo de commit es de forma libre y PUEDE consistir en cualquier número de párrafos separados por nuevas líneas.
Pie
-
Se PUEDEN proporcionar uno o más pies una línea en blanco después del cuerpo. Cada pie DEBE consistir en un token de palabra, seguido de un separador
:<space>o<space>#, seguido de un valor de cadena (inspirado en la convención de trailers de git). -
El token de un pie DEBE usar
-en lugar de caracteres de espacio en blanco, por ejemplo,Acked-by(esto ayuda a diferenciar la sección de pie del cuerpo multipárrafo). Excepción:BREAKING CHANGEPUEDE usarse también como token. -
El valor de un pie PUEDE contener espacios y nuevas líneas. El análisis DEBE terminar cuando se observe el siguiente par token/separador de pie válido.
Cambios Disruptivos
-
Los cambios disruptivos DEBEN indicarse en el prefijo tipo/ámbito de un commit, o como una entrada en el pie.
-
Si se incluye como pie, un cambio disruptivo DEBE consistir en el texto en mayúsculas
BREAKING CHANGE, seguido de dos puntos, espacio y descripción, por ejemplo,BREAKING CHANGE: las variables de entorno ahora tienen prioridad sobre los archivos de configuración. -
Si se incluye en el prefijo tipo/ámbito, los cambios disruptivos DEBEN indicarse mediante
!inmediatamente antes de:. Si se usa!,BREAKING CHANGE:PUEDE omitirse del pie, y la descripción del commit DEBERÁ usarse para describir el cambio disruptivo.
Reglas Adicionales
-
Se PUEDEN usar tipos distintos de
featyfixen los mensajes de commit, por ejemplo,docs: actualizar documentación de referencia. -
Las unidades de información que componen los Commits Convencionales NO DEBEN tratarse como sensibles a mayúsculas/minúsculas por los implementadores, excepto
BREAKING CHANGEque DEBE estar en mayúsculas. -
BREAKING-CHANGEDEBE ser sinónimo deBREAKING CHANGEcuando se usa como token en un pie.
Mejores Prácticas de Descripción
Basadas en las guías de mensajes de commit de Angular:
Guías de Resumen/Descripción
- Usa imperativo, tiempo presente: "change" no "changed" ni "changes"
- No capitalices la primera letra
- Sin punto (.) al final
- Mantén todo el encabezado (tipo + ámbito + descripción) por debajo de 72 caracteres
Buenos Ejemplos
feat: añadir validación para entrada de email
fix: manejar puntero nulo en servicio de usuario
docs: actualizar instrucciones de instalación
refactor: simplificar flujo de autenticación
Malos Ejemplos (Evitar)
feat: Añadida validación para entrada de email # Tiempo pasado
fix: Maneja puntero nulo en servicio de usuario # Tercera persona
docs: Actualizar instrucciones de instalación. # Punto al final, capitalizado
FEAT: add validation # Tipo en mayúsculas (inconsistente)
Guías del Cuerpo
- Usa imperativo, tiempo presente (igual que el resumen)
- Explica la motivación del cambio
- Incluye comparación del comportamiento anterior vs. nuevo cuando sea útil
- El cuerpo DEBE comenzar con una línea en blanco después de la descripción
- Mínimo recomendado: 20 caracteres cuando el cuerpo está presente
Cambios Disruptivos
Métodos para Indicar Cambios Disruptivos
Tres enfoques equivalentes:
-
Notación de pie:
feat: permitir que el objeto de configuración proporcionado extienda otras configuraciones BREAKING CHANGE: la clave `extends` en el archivo de configuración ahora se usa para extender otros archivos de configuración -
Sufijo de tipo con
!:feat!: eliminar soporte para Node 6 -
Sufijo de tipo+ámbito con
!:feat(api)!: enviar un email al cliente cuando se envía un producto
Reglas
BREAKING CHANGEDEBE estar en mayúsculasBREAKING-CHANGEes sinónimo cuando se usa como token de pie- Los cambios disruptivos DEBEN correlacionarse con un incremento de versión MAJOR en SemVer
Correlación con Versionado Semántico
flowchart TD
Start([Analizar Commits]) --> CheckBreaking{¿Algún commit tiene<br/>BREAKING CHANGE<br/>o !?}
CheckBreaking -->|Sí| Major[Incremento MAJOR<br/>X.0.0]
CheckBreaking -->|No| CheckFeat{¿Algún commit<br/>es feat?}
CheckFeat -->|Sí| Minor[Incremento MINOR<br/>0.X.0]
CheckFeat -->|No| CheckFix{¿Algún commit<br/>es fix?}
CheckFix -->|Sí| Patch[Incremento PATCH<br/>0.0.X]
CheckFix -->|No| NoChange[Sin cambio de versión]
Major --> End([Lanzamiento])
Minor --> End
Patch --> End
NoChange --> End
Mapeo de Tipo de Commit a Versión
| Tipo de Commit | Incremento de Versión |
|---|---|
fix | PATCH (0.0.X) |
feat | MINOR (0.X.0) |
BREAKING CHANGE o ! | MAJOR (X.0.0) |
Razón: Permite el versionado semántico automatizado basado en el historial de commits.
Patrones de Validación
Expresión Regular de Encabezado
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?:\s.+$
Ejemplo de Validación en Python
import re
CONVENTIONAL_COMMIT_PATTERN = re.compile(
r"^(?P<type>feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)"
r"(?:\((?P<scope>[^)]+)\))?"
r"(?P<breaking>!)?"
r":\s"
r"(?P<description>.+)$"
)
def validate_header(header: str) -> bool:
"""Valida que el encabezado del commit siga Commits Convencionales."""
return bool(CONVENTIONAL_COMMIT_PATTERN.match(header))
def parse_header(header: str) -> dict | None:
"""Analiza el encabezado del commit en componentes."""
match = CONVENTIONAL_COMMIT_PATTERN.match(header)
if not match:
return None
return {
"type": match.group("type"),
"scope": match.group("scope"),
"breaking": bool(match.group("breaking")),
"description": match.group("description"),
}
Ejemplos Completos
Commits Simples
feat: añadir autenticación de usuario
fix: evitar fallo en entrada vacía
docs: corregir ortografía de CHANGELOG
Commits con Ámbito
feat(lang): añadir idioma polaco
feat(parser): añadir capacidad para analizar arrays
fix(auth): manejar caducidad de token correctamente
Cambios Disruptivos
feat: permitir que el objeto de configuración proporcionado extienda otras configuraciones
BREAKING CHANGE: la clave `extends` en el archivo de configuración ahora se usa para extender otros archivos de configuración
feat!: enviar un email al cliente cuando se envía un producto
feat(api)!: enviar un email al cliente cuando se envía un producto
chore!: eliminar soporte para Node 6
BREAKING CHANGE: usar funcionalidades de JavaScript no disponibles en Node 6.
Cuerpo Multipárrafo con Pies
fix: evitar carrera de solicitudes
Introducir un id de solicitud y una referencia a la última solicitud. Descartar
respuestas entrantes que no sean de la última solicitud.
Eliminar timeouts que se usaban para mitigar el problema de carrera pero que
ya son obsoletos.
Revisado-por: Z
Refs: #123
Commit de Reversión
revert: que nunca más hablemos del incidente del fideo
Refs: 676104e, a215868
Mejora de Rendimiento
perf: reducir asignación de memoria en el parser en un 40%
Reemplazar concatenación de cadenas con patrón StringBuilder.
Los resultados de benchmarks muestran una reducción del 40% en asignaciones de heap.
Refs: #456
Refactorización
refactor: extraer lógica de autenticación en un módulo separado
Mover funciones relacionadas con autenticación de utils.py a auth.py.
Sin cambios funcionales.
Cambios de Build/CI
ci: añadir Node 18 a la matriz de pruebas
build: actualizar webpack de v4 a v5
- Actualizar webpack.config.js para compatibilidad con v5
- Reemplazar plugins obsoletos
- Actualizar todas las dependencias de loaders
Refs: #789
Cambios de Prueba y Estilo
test: añadir pruebas unitarias para validación de usuario
Cubrir casos extremos para validación de email y fortaleza de contraseña.
style: formatear código según configuración de prettier
chore: actualizar .gitignore para excluir archivos de IDE
Integración con Herramientas de Validación
Configuración de commitlint
Valida commits con commitlint usando la configuración Angular:
# Instalar commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Crear configuración
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
# Probar mensaje de commit
echo 'feat(api): añadir nuevo endpoint' | npx commitlint
Para una guía completa de configuración de commitlint, usa las indicaciones de este documento. Si tu espacio de trabajo tiene un plugin de commitlint instalado, puedes delegar en él para reglas y ejemplos específicos del proyecto.
Hooks Pre-commit
Impón el formato del mensaje de commit con hooks pre-commit. Si tu espacio de trabajo tiene un plugin de pre-commit instalado, puedes usarlo para obtener guías de configuración de hooks; de lo contrario, configura los hooks directamente.
Generación de Changelog
Genera changelogs a partir de Commits Convencionales usando semantic-release:
// release.config.js
module.exports = {
branches: ['main'],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/changelog',
'@semantic-release/git',
],
};