Skill: Git Commit con Conventional Commits
Preparar y ejecutar commits estandarizados según
Conventional Commits, inferidos del diff real del repositorio.
Alcance: captura un único cambio lógico con mensaje semántico. No hace push, no toca configuración global de git, no aplica operaciones destructivas. Preguntar lo que no esté claro — no inventar tipo, scope ni descripción.
Formato canónico:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Cómo preguntar al usuario
Usar la herramienta de preguntas estructuradas del cliente (opciones tappables). Reglas:
- Una pregunta por turno; máximo tres en un mismo bloque.
- Opciones cortas y mutuamente excluyentes (2–4); entrada libre solo si no hay forma de enumerar opciones.
- No repreguntar lo que ya está en el contexto, , el diff o la propuesta ya mostrada.
- Una sola tanda al inicio para resolver ambigüedades; excepciones deliberadas por turno: propuesta de commit, commit en rama protegida, archivo sensible detectado.
- Fallback: prosa con opciones enumeradas (1, 2, 3…) si el cliente no expone la herramienta.
Resolución de idioma
- en (claves legacy , , como fallback).
- Idioma del turno del usuario.
- Preguntar y persistir en .
Afecta a la parte en lenguaje natural (descripción, body, footers). Tipo y scope permanecen en inglés salvo acuerdo explícito del equipo.
Selección de flujo
Convenciones del mensaje
- Tipo y scope: palabras clave en inglés salvo convención explícita del equipo.
- Descripción: verbo imperativo presente, máximo 72 caracteres, sin punto final, sin mayúscula inicial.
- Breaking change: tras tipo/scope () o footer
BREAKING CHANGE: <detalle>
.
- Referencias a issues: footer o cuando el usuario aporte el número.
Tipos de commit
| Tipo | Propósito |
|---|
| Nueva funcionalidad |
| Corrección de bug |
| Solo documentación |
| Formato/estilo (sin lógica) |
| Refactorización (sin feature/fix) |
| Mejora de rendimiento |
| Añadir o actualizar tests |
| Sistema de build / dependencias |
| Cambios en CI / configuración |
| Mantenimiento / miscelánea |
| Revertir commit |
Inferencia desde el diff
Aplicar en orden; si nada encaja con confianza, preguntar al usuario.
Tipo
| Patrón observado | Tipo |
|---|
| Solo , , , | |
| Solo , , , | |
| Solo archivos de CI (, , etc.) | |
| Solo archivos de build (, deps de , , etc.) | |
| Solo cambios de formato/espaciado sin lógica modificada | |
| Archivos nuevos bajo que añaden funcionalidad usable por el cliente | |
| Modificación de lógica existente que corrige un comportamiento descrito como bug | |
| Reestructuración interna sin cambiar comportamiento observable | |
| Cambios cuyo único objetivo es ejecución más rápida o menor consumo | |
| Reversión de un commit anterior | |
| Configuración, scripts auxiliares, dependencias menores | |
Scope
- Todos los archivos bajo un único módulo () → scope = nombre del módulo.
- Todos bajo una feature o dominio identificable → scope = nombre de la feature.
- Cambio transversal a una capa (, , , ) → scope = nombre de la capa.
- Sin scope claro → omitirlo. No inventar genéricos (, , ).
Descripción
Verbo imperativo presente (
,
,
,
,
). Indicar
qué cambia, no
cómo se implementó. Máximo 72 caracteres. Sin punto final. Sin mayúscula inicial.
Detección de secretos en el diff
Ejecutar antes de aceptar el staging:
bash
git diff --staged | grep -nEi 'password[[:space:]]*=|api[_-]?key|secret[[:space:]]*=|token[[:space:]]*=|BEGIN (RSA |EC |OPENSSH |DSA )?PRIVATE KEY|aws_access_key_id|aws_secret_access_key|-----BEGIN CERTIFICATE-----'
Si hay coincidencias,
o si el staging incluye
,
,
,
,
,
:
detener y reportar al usuario los archivos y líneas detectadas. No commitear hasta que el usuario los retire (
git restore --staged <ruta>
) o confirme explícitamente que es intencional.
Flujo: Commit estándar
- Inspeccionar estado y diff:
bash
git status --porcelain
git diff --staged # si hay staging
git diff # si no hay staging
git rev-parse --abbrev-ref HEAD
- Ajustar staging: añadir archivos faltantes del cambio (); retirar no relacionados (
git restore --staged <ruta>
).
- Inferir tipo, scope y descripción desde el diff.
- Decidir body (solo si aporta contexto no obvio) y footer (, ).
- Ejecutar Validación antes de ejecutar. Si falla, detener.
- Mostrar Propuesta de commit y esperar confirmación.
- Ejecutar el commit:
bash
# Una línea
git commit -m "<type>[scope]: <description>"
# Multi-línea
git commit -m "$(cat <<'EOF'
<type>[scope]: <description>
<optional body>
<optional footer>
EOF
)"
- Reportar SHA corto (
git rev-parse --short HEAD
) y mensaje del commit creado.
Flujo: Múltiples cambios lógicos
- Agrupar archivos por afinidad desde el diff (área, tipo de cambio, intención).
- Proponer al usuario la lista ordenada de commits planeados: tipo/scope, archivos, descripción tentativa.
- Esperar confirmación o ajustes antes de tocar staging.
- Por cada grupo confirmado, en orden:
- (preserva el working tree) para vaciar staging.
- del grupo.
- Ejecutar Validación antes de ejecutar.
- Mostrar Propuesta de commit y esperar confirmación.
- y registrar el SHA.
- Reportar la secuencia final de SHAs y mensajes en el orden ejecutado.
Flujo: Recuperación tras fallo de hook
- Leer el mensaje del hook; aplicar las correcciones en el working tree.
- Re-stagear los archivos corregidos: .
- Crear un commit nuevo con el mismo mensaje acordado — no salvo petición explícita.
- No usar salvo petición explícita.
- Si el problema es del propio hook (config rota, no del código): informar al usuario y esperar instrucciones.
Propuesta de commit
Mostrar antes de ejecutar
y esperar confirmación mediante la herramienta de preguntas estructuradas:
Propuesta:
tipo: <type>
scope: <scope o "(omitido)">
descripción: <description>
archivos:
- <archivo 1>
- <archivo 2>
body: <texto o "(ninguno)">
footer: <texto o "(ninguno)">
Opciones:
/
/
/
/
. Si el usuario ajusta, aplicar y volver a mostrar la propuesta.
Validación antes de ejecutar
- Sin secretos en staging (ejecutar Detección de secretos).
- Un solo cambio lógico por commit.
- Sin , , , salvo petición explícita.
- Rama segura, o usuario confirmó commit directo en ///.
Si hay conflicto:
⚠️ No es posible commitear todavía:
- <razón concreta>
- <archivo, línea o detalle>
Checklist antes de ejecutar
Información:
Validación:
Formato:
Confirmación:
Ejemplos
Ejemplo 1 — Commit estándar
- Entrada: «Acabo de corregir el bug del cupón vacío en el checkout; diff solo en .»
- Salida:
git commit -m "fix(cart): validate empty coupon before apply"
Ejemplo 2 — Cambios mezclados
- Entrada: Diff incluye , y con una ruta nueva.
- Salida: Dos commits:
docs: update API endpoint reference
y feat(users): add endpoint to fetch user preferences
.
Ejemplo 3 — Breaking change
- Entrada: Diff renombra endpoint público → rompiendo clientes existentes.
- Salida:
feat(api)!: rename users endpoint to v2
BREAKING CHANGE: `/v1/users` removed; clients must migrate to `/v2/users`.
Ejemplo 4 — Información incompleta
- Entrada: «Haz commit de lo que está en staging.» Cambios cruzan varios módulos sin patrón claro.
- Comportamiento: Preguntar la intención principal o proponer agrupación. No generar mensaje genérico.
Ejemplo 5 — Fallo de hook
- Entrada: Hook de lint falla en tras .
- Comportamiento: Aplicar el formateo, , commit nuevo con el mismo mensaje. Sin ni .
Ejemplo 6 — Secreto detectado
- Entrada: Diff staged incluye con .
- Comportamiento: Detener, reportar archivo y línea. Sugerir
git restore --staged config/.env.local
. No commitear sin confirmación explícita.
Anti-patterns
- Commit que mezcla features, fixes y refactors sin relación.
- Mensajes vagos (, , , ).
- Inventar tipo o scope cuando el diff no lo respalda.
- Incluir archivos sensibles (, claves) sin detección y confirmación.
- Saltar la detección de secretos confiando en inspección visual.
- Saltar hooks con por comodidad.
- Usar tras fallo de hook en lugar de crear un commit nuevo.
- Force push a / .
- Modificar configuración global de git sin permiso explícito.
- Ejecutar sin mostrar la propuesta y esperar confirmación.
- Lanzar preguntas como prosa libre cuando el cliente expone la herramienta estructurada.
- Narrar el trabajo al usuario — reportar solo SHA, mensaje final y pendientes.