Buenas prácticas de Git en 2026: la checklist del profesional
Commits atómicos, mensajes claros, secretos fuera del repo y force push seguro: la checklist de buenas prácticas de Git para trabajar con IA.
Tu historial de Git no es un diario personal. Es la documentación que lee tu equipo cuando algo se rompe a las tres de la tarde, y la que lees tú dentro de seis meses cuando no recuerdas por qué esa línea existe. En 2026, con un agente escribiendo buena parte de tus diffs, esa documentación se llena de cambios que tú no has tecleado. Por eso las buenas prácticas de Git importan más ahora, no menos. Aquí tienes la checklist que aplico y que puedes empezar a usar hoy mismo.
¿Por qué la disciplina de Git importa más ahora que la IA escribe tus diffs?
Porque un agente produce cambios más rápido de lo que tú los revisas, y Git es el único sitio donde queda constancia de qué entró y por qué. Cuando tecleabas cada línea, entendías cada cambio por el simple hecho de haberlo escrito. Ese entendimiento gratis desapareció.
Ahora le pides a la IA «añade paginación al listado de facturas» y te devuelve doscientas líneas repartidas en cinco archivos. Algunas son exactamente lo que querías. Otras tocan un helper compartido «de paso», o meten una dependencia que no habías pedido. Si aceptas todo el bloque y lo commiteas con un «wip», acabas de meter en la historia del proyecto algo que nadie ha leído.
La disciplina de Git es lo que te devuelve el control. No frena a la IA. Convierte su velocidad en algo que tu equipo puede revisar, revertir y entender. El resto de este post es cómo hacerlo, comando a comando.
Commits atómicos: una idea por commit
Un commit atómico contiene un único cambio lógico completo, y nada más. Si arreglas un bug y de camino renombras tres variables y actualizas una dependencia, eso son tres commits, no uno.
La prueba práctica es la frase: si para describir lo que hace un commit necesitas la palabra «y» («arregla el login y refactoriza el router»), casi siempre son dos. Sepáralos.
¿Por qué molestarse? Porque el día que ese arreglo del login rompa producción, quieres poder hacer git revert de esa corrección sin arrastrar también el refactor del router. Un commit que mezcla cosas no se puede deshacer en parte. O te lo quedas todo, o lo pierdes todo. La granularidad que metes hoy es la libertad que tienes mañana para revertir, revisar y hacer git bisect.
Esto engancha directo con cómo trabajas con la IA: si le pides una sola cosa por sesión, sus diffs ya salen casi atómicos. Si le pides cuatro, tú tendrás que separarlos después. El trabajo fino de partir un cambio grande en commits que cuentan una historia lo desarrollo en la guía de commits atómicos; aquí me quedo con la regla: una idea, un commit.
¿Cómo se escribe un mensaje de commit que sirva a tu equipo?
El asunto va en imperativo y describe qué hace el commit; el cuerpo explica por qué. El imperativo no es un capricho de estilo: los propios mensajes que genera Git («Merge branch…», «Revert…») están en imperativo, así que el tuyo encaja con el resto.
Compara estos dos:
# Mal: pretérito, sin contexto, inútil dentro de seis meses
Arreglado el bug del IVA
# Bien: asunto en imperativo + cuerpo con el porqué
Corrige el IVA en facturas de clientes exentos
El total aplicaba el 21% aunque el cliente tuviera
tax_exempt=true. Ahora se comprueba la exención antes
de calcular el tipo. Detectado en la factura #482.
El asunto malo te dice qué pasó. El bueno te dice qué buscar cuando el mismo bug reaparezca. Esa diferencia es la que separa un historial que se lee de uno que se ignora.
Un detalle que ahorra discusiones de equipo: el asunto, corto (apunta a unos 50 caracteres), una línea en blanco, y luego el cuerpo. Esa línea en blanco no es decorativa. Git usa la primera línea como resumen en git log --oneline, en las notificaciones de GitHub y en git blame --porcelain. Si la juntas con el cuerpo, rompes ese resumen.
Secretos fuera del repo: el .gitignore que deberías tener
Un secreto commiteado sigue en la historia aunque lo borres después, así que la única defensa real es que nunca entre. Y entra siempre por el mismo sitio: el .env con la clave de la base de datos o el token de la API que subes «sin querer» junto al resto del cambio.
Un .gitignore mínimo para cualquier proyecto:
# Secretos y entorno: nunca en el repo
.env
.env.*
*.pem
config/credentials.json
# Artefactos y dependencias
node_modules/
dist/
.DS_Store
Si ya has commiteado un .env, añadirlo al .gitignore no lo saca de la historia: Git sigue rastreando lo que ya rastreaba. Tienes que quitarlo del índice con git rm --cached .env, commitear esa salida, y (esto es lo importante) rotar el secreto, porque cualquiera con acceso al historial ya lo ha visto. Un secreto filtrado se considera quemado desde el segundo en que tocó el repo.
Con la IA esto se vuelve más traicionero. Le pides un script de despliegue y te lo devuelve con la contraseña «de ejemplo» hardcodeada, o con un .env.production de regalo. Si aceptas el diff sin mirarlo, ese secreto de ejemplo puede acabar en el repo. Que es la razón de la siguiente sección.
Nombres de rama: una convención que tu equipo pueda leer
Una rama bien nombrada dice de un vistazo qué tipo de cambio es y de qué va, sin que tengas que abrir nada. El patrón que mejor funciona en equipo es tipo/descripción-corta:
# git switch es la forma moderna y estable de crear y cambiar de rama
git switch -c feat/exportar-facturas-pdf
Prefijos habituales: feat/ para funcionalidad nueva, fix/ para correcciones, chore/ para tareas de mantenimiento, docs/ para documentación. Lo importante no es cuál eliges, sino que todo el equipo use el mismo y lo respete. Una convención que solo sigues tú no es una convención.
Uso git switch en lugar de git checkout a propósito. checkout hace demasiadas cosas distintas (cambia de rama, restaura archivos, mueve el HEAD), y esa sobrecarga es una fuente clásica de sustos. git switch solo cambia de rama y git restore solo restaura archivos. Separar esas dos operaciones en dos comandos hace mucho más difícil pisar tu trabajo por error. Cómo encaja cada convención de ramas en un flujo de equipo completo (Gitflow, GitHub Flow, trunk-based) lo comparo en la guía de flujos de trabajo con Git.
Nunca reescribas historia que otros ya tienen
Reescribir un commit que ya está en una rama compartida rompe el historial de todos los que lo tienen. La regla es simple: puedes reescribir lo que solo vive en tu máquina; en cuanto algo está en main o en una rama que otros usan, es historia pública y no se toca.
El peligro concreto tiene nombre: git push --force. Sobrescribe la rama remota pase lo que pase, incluidos los commits que un compañero subió mientras tú trabajabas. Se los borra sin avisar. Existe una versión mucho más segura, --force-with-lease, y esta es la diferencia:
| Situación | --force | --force-with-lease |
|---|---|---|
| Comportamiento base | Sobrescribe el remoto siempre | Sobrescribe solo si el remoto está donde tú crees que está |
| Un compañero subió commits que tú no tienes | Los pierde sin avisar | Falla y aborta el push, así te enteras |
| Cuándo tiene sentido | Casi nunca | Al re-subir tu propia rama después de un rebase |
--force-with-lease no es magia infalible. Compara el remoto contra tu rama de seguimiento local, y algunos editores hacen git fetch en segundo plano; si eso actualiza tu referencia de seguimiento justo antes del push, el «cerrojo» ya no protege nada. Para blindarlo del todo, Git tiene --force-if-includes, que además exige que hayas integrado localmente lo que hay en el remoto. Pero el hábito que quiero que te lleves es más básico: sustituye --force por --force-with-lease en tu memoria muscular y en los alias del equipo. Ese cambio de una palabra evita la mayoría de los desastres.
Revisa los diffs de la IA antes de commitear
Aceptar un diff generado sin leerlo es la forma más rápida de meter un bug con tu nombre en el git blame. El agente firma la sugerencia; el commit lo firmas tú. Y Git ya trae las herramientas para revisar antes de que nada entre en la historia.
git add -p # aprueba trozo a trozo, no el archivo entero
git diff --staged # mira exactamente lo que vas a commitear
git commit
git add -p te presenta el cambio por trozos (hunks) y te pregunta por cada uno si lo quieres. Aquí es donde cazas la línea de más que metió la IA, el console.log olvidado, la dependencia que no pediste. En vez de tragarte doscientas líneas de golpe, apruebas las que entiendes y dejas fuera las que no.
git diff --staged es el último control antes de disparar: muestra lo que está preparado para el commit, ni más ni menos. Si lo que ves ahí no lo sabrías explicar en la revisión de código, no lo commitees todavía. Este par de comandos convierte «confío en que la IA lo hizo bien» en «he visto exactamente qué entra». Con un agente de por medio, ese paso deja de ser opcional.
Errores comunes que arruinan un historial
El commit «wip» de doscientas líneas. Es el más común y el más caro. Mezcla features, arreglos y ruido en un bloque imposible de revisar y de revertir por partes. La cura es un hábito, no tecnología: commitea cuando termines una idea, no cuando te acuerdes.
El mensaje «fix» o «cambios». No documenta nada. Dentro de un mes, git log es una lista de «fix, fix, cambios, fix» que no le sirve a nadie, empezando por ti.
Creer que git commit -am añade archivos nuevos. No lo hace, y este malentendido cuesta bugs de verdad. El flag -a prepara los archivos modificados o borrados que Git ya estaba rastreando; los archivos nuevos que Git nunca ha visto se quedan fuera hasta que haces git add[1]. Crees que subiste ese utils/pdf.ts recién creado y en realidad se quedó en tu máquina. La build de tu compañero peta con un import que no existe.
--force sobre una rama compartida. Ya tiene su sección entera arriba. Si solo te llevas una cosa de este post, que sea sustituirlo por --force-with-lease.
La checklist del profesional
- Cada commit contiene un único cambio lógico (si necesitas «y» para describirlo, sepáralo)
- El asunto del mensaje va en imperativo y el cuerpo explica el porqué
-
.env,*.pemy credenciales están en.gitignoreantes del primer commit - Las ramas siguen una convención de equipo del tipo
feat/descripcion-corta - Nunca haces
--forcesobre una rama compartida; usas--force-with-lease - Revisas cada diff de la IA con
git add -pygit diff --stagedantes de commitear - Un secreto que tocó el repo se rota, no solo se borra
Aplica estos siete puntos durante una semana y tu historial pasa de ser un vertedero a ser documentación que tu equipo agradece. Si trabajas en equipo, el siguiente paso es acordar estas reglas entre todos: cómo se revisan los PRs, quién mergea y cuándo, todo eso lo desarrollo en la guía para trabajar en equipo con Git y GitHub.
Leer la checklist es el primer paso; interiorizarla se consigue practicando con un repositorio de verdad. Si quieres montar estos hábitos desde cero, con ejercicios guiados y correcciones sobre commits reales, los trabajamos paso a paso en el curso de Git de cero a profesional.
Si quieres que te avise cuando publique el resto de las guías de esta serie sobre Git, déjame tu correo:
Un concepto nuevo cada semana
Fuentes
- git commit (documentación oficial de Git): respalda que el flag
-asolo prepara archivos ya rastreados y no añade archivos nuevos. - git switch (documentación oficial de Git): comando estándar para crear (
-c) y cambiar de rama; ya no lleva la nota de experimental. - git push (documentación oficial de Git): describe
--force-with-leasey cómo comprueba el valor esperado del remoto antes de sobrescribir. - git blame (documentación oficial de Git): el formato por defecto anota hash, autor, fecha y número de línea; el mensaje del commit solo aparece con
--porcelain.
Preguntas Frecuentes
¿git commit -a añade los archivos nuevos que he creado?
No. -a (y por tanto -am) solo prepara cambios en archivos que Git ya estaba rastreando: los modificados y los borrados[1]. Un archivo nuevo que nunca has añadido con git add se queda fuera del commit por mucho -a que le pongas. Es uno de los malentendidos más caros entre quienes empiezan con buenas prácticas de Git, porque el commit «parece» completo y no lo está.
¿git blame muestra el mensaje del commit de cada línea?
En su formato por defecto, no: te da el hash abreviado, el autor, la fecha y el número de línea[4]. Para ver el resumen del mensaje asociado a cada línea necesitas git blame --porcelain, que sí incluye el campo summary. Si quieres el mensaje completo, copia el hash que te da blame y haz git show <hash>.
¿git switch sigue siendo experimental?
No. Se introdujo como experimental en 2019, pero es una parte estable y recomendada de Git desde hace años; la nota de «experimental» se retiró de la documentación oficial[2]. Puedes usar git switch y git restore con total confianza en cualquier versión razonablemente actual. git checkout sigue existiendo por compatibilidad, pero para el día a día los dos comandos nuevos son más claros y más seguros.
¿Puedo hacer force push en mi propia rama de feature?
Sí, y es habitual. Después de un rebase o un commit --amend en tu rama personal, tienes que reescribir lo que ya subiste, y ahí el force push es legítimo. Hazlo siempre con --force-with-lease en vez de --force[3]: si nadie más ha tocado la rama, funciona igual; si alguien la tocó, falla y te avisa en lugar de borrar su trabajo. Forzar tu propia rama es legítimo; forzar una que otros usan puede borrar su trabajo.
¿Cada cuánto debo commitear si quiero seguir buenas prácticas de Git?
Cuando termines una idea completa, no por reloj ni por número de líneas. Un commit debería dejar el proyecto en un estado coherente: compila, los tests que había pasan, y el cambio se puede describir en una frase sin «y». Eso suele caer en varias veces al día si trabajas en cosas pequeñas. Si llevas horas sin commitear, casi seguro que ya tienes dentro más de un cambio lógico esperando a que los separes.