Flujo de trabajo
Ejecuta estos pasos en orden. Detente e informa al usuario si algún paso falla.
1. Evaluar el árbol de trabajo
Ejecuta git status y git diff (tanto staged como unstaged) para entender qué cambió. Si no hay cambios en absoluto, dile al usuario que no hay nada que confirmar y detente.
2. Limpiar submódulos sucios
Si git status muestra submódulos con "(modified content)" pero no hay cambios staged o intencionados en los punteros de submódulos, se trata de sub-submódulos anidados que se desviaron (típicamente por una actualización recursiva con --remote). Para cada submódulo sucio, ejecuta git -C <ruta-del-submódulo> submodule update --init para restaurar las referencias anidadas a los commits esperados por el submódulo padre. Después de la limpieza, vuelve a verificar git status para confirmar que la suciedad ha desaparecido. NO hagas stage de cambios en los punteros de submódulos a menos que el usuario los haya cambiado explícitamente.
3. Hacer stage de todo a menos que el usuario especifique lo contrario
Si el usuario no especificó archivos concretos, haz stage de todos los cambios (trackeados y no trackeados) con git add -A. Si el usuario nombró archivos o rutas específicas, haz stage solo de esos.
4. Linter y auto-corrección
Antes de confirmar, detecta el linter del proyecto y ejecútalo con auto-corrección en los archivos staged. Orden de detección:
- Objetivo lint a nivel de proyecto primero: si el Makefile tiene un objetivo
lintolint:fix, o package.json tiene un scriptlintolint:fix, prefiérelo — respeta las convenciones del proyecto. Pasa a la detección por lenguaje solo si no existe un objetivo a nivel de proyecto. - Go (go.mod presente): ejecuta
gofmt -wen los archivos .go staged, luegogo vet ./... - JavaScript/TypeScript (package.json presente): ejecuta
npx eslint --fixen los archivos JS/TS staged si existe una configuración de ESLint. Si Prettier está configurado, ejecuta tambiénnpx prettier --writeen esos archivos. - Python (pyproject.toml, setup.py o requirements.txt presente): ejecuta
ruff check --fixyruff formaten los archivos .py staged si Ruff está configurado. Si no, prueba conblacksi está instalado. Si no, prueba conflake8(solo informe, sin auto-corrección). - Rust (Cargo.toml presente): ejecuta
cargo fmtycargo clippy --fix --allow-dirty - No se detectó linter: omite este paso y continúa.
Después de la auto-corrección, vuelve a hacer stage de los archivos modificados con git add -u. Si el linter reporta errores que no pudieron corregirse automáticamente, detente e infórmalos al usuario — no confirmes con fallos de lint conocidos.
Si se detecta un linter pero el binario no está instalado, advierte al usuario y pregúntale si desea continuar sin linting o abortar.
5. Generar el mensaje de commit
Analiza el diff staged para producir un mensaje Conventional Commit:
tipo(ámbito): resumen breve
Cuerpo opcional con contexto sobre qué cambió y por qué.
Reglas:
- tipo: uno de feat, fix, refactor, docs, test, chore, ci, perf, style, build
- ámbito: opcional pero preferido — derívalo del paquete, módulo o directorio principal tocado. Omítelo solo cuando los cambios abarquen demasiadas áreas para que un solo ámbito tenga sentido.
- Línea de resumen: minúsculas, modo imperativo, sin punto, máximo 72 caracteres.
- Cuerpo: añádelo solo cuando el diff no sea trivial y el resumen por sí solo no le dé suficiente contexto a un revisor. Mantenlo conciso.
- Cambios lógicos múltiples: elige el dominante para tipo/ámbito, menciona los cambios secundarios en el cuerpo. NO dividas en múltiples commits a menos que el usuario lo pida explícitamente.
- Cambios disruptivos: añade un pie de página BREAKING CHANGE o usa el sufijo
!(ej., feat!: ...). - Si el linter auto-corrigió archivos, menciónalo en el cuerpo (ej., "Incluye auto-correcciones de gofmt.").
6. Confirmar (commit)
Ejecuta git commit con el mensaje generado. Usa -m para mensajes solo de resumen. Para mensajes con cuerpo, escribe a un archivo temporal y usa git commit -F para preservar saltos de línea, luego limpia el archivo temporal.
7. Sincronizar con el remoto
Determina el nombre de la rama actual. Luego:
- Si la rama tiene un upstream, ejecuta
git push. - Si la rama no tiene upstream, ejecuta
git push -u origin <nombre-de-rama>. - Si el push es rechazado porque el remoto está adelantado, ejecuta
git pull --rebasey luego push de nuevo. Si el rebase produce conflictos, detente e informa — no resuelvas conflictos de fusión automáticamente.
8. Confirmar
Informa al usuario:
- Hash del commit (forma corta)
- Mensaje de commit utilizado
- Nombre de la rama y estado de sincronización remota
- Archivos cambiados, inserciones, eliminaciones (de
git diff --statdel commit) - Qué linter se ejecutó (o que no se detectó ninguno)
Casos extremos
- Sin remoto configurado: confirma localmente e informa al usuario.
- HEAD desprendido: advierte antes de confirmar, sugiere crear una rama primero.
- Solo archivos no trackeados: hazles stage y confírmalos normalmente.
- Respeta .gitignore — nunca fuerces la adición de archivos ignorados a menos que el usuario lo pida explícitamente.