Edición Avanzada del Historial de Git: Modificación de Commits y Rebase Interactivo
Usa git commit --amend y el rebase interactivo para limpiar el historial local sin interrumpir ramas compartidas.
Edición Avanzada del Historial de Git: Modificación de Commits y Rebase Interactivo
La edición avanzada del historial de Git te ayuda a limpiar los commits antes de que formen parte del historial compartido. Cuando entiendes cómo modificar commits y usar el rebase interactivo, puedes corregir pequeños errores, combinar commits ruidosos y presentar una historia más clara para la revisión de código.
La regla clave es simple: editar el historial local es normal, pero reescribir el historial compartido requiere cuidado. Los comandos son potentes porque cambian los IDs de los commits, no solo los mensajes.
Qué Cambia Realmente la Edición del Historial de Git
Cada commit de Git tiene un ID basado en su contenido, metadatos, commit padre, autor, fecha y mensaje. Si modificas un commit o lo reescribes durante un rebase, Git crea un nuevo commit con un nuevo ID.
Eso está bien cuando el commit solo existe en tu máquina. Es arriesgado cuando otras personas ya han extraído el commit antiguo. Sus ramas pueden seguir apuntando al historial antiguo, mientras que la tuya apunta al historial reescrito.
Usa la edición del historial para:
- Corregir un error tipográfico en el mensaje del último commit.
- Agregar un archivo olvidado a tu último commit local.
- Fusionar varios commits de trabajo en progreso antes de abrir una solicitud de extracción.
- Reordenar commits locales para que los cambios relacionados sean más fáciles de revisar.
- Dividir un commit local grande en commits lógicos más pequeños.
Evita la edición del historial en:
- Ramas principales.
- Ramas de lanzamiento.
- Ramas de características compartidas utilizadas por varias personas.
- Cualquier rama con etiquetas de despliegue o commits sensibles a auditorías.
Antes de comenzar, verifica en qué rama estás y qué se ha enviado:
git status
git branch --show-current
git log --oneline --decorate -5
Si no estás seguro de si reescribir es seguro, crea una rama de respaldo:
git branch backup-before-rebase
Esa rama te da un punto de recuperación conocido si el rebase sale mal.
Modificar el Último Commit
git commit --amend reemplaza el commit más reciente con uno nuevo. Es la forma más rápida de corregir el último commit antes de que alguien más dependa de él.
Para editar solo el mensaje del commit:
git commit --amend
Git abre tu editor con el mensaje actual. Guarda el mensaje corregido y Git crea un commit de reemplazo.
Para agregar un archivo olvidado al último commit:
git add ruta/al/archivo
git commit --amend --no-edit
La bandera --no-edit mantiene el mensaje existente. Esto es útil cuando el mensaje del commit ya es correcto y solo olvidaste preparar un cambio.
Aquí hay un escenario común. Haces un commit de una actualización de Dockerfile, luego notas que olvidaste el cambio relacionado de .dockerignore:
git add Dockerfile
git commit -m "Mejorar el almacenamiento en caché de la compilación de Docker"
git add .dockerignore
git commit --amend --no-edit
Ahora la rama tiene un commit limpio en lugar de un segundo commit que dice "archivo olvidado." Eso facilita la revisión.
Si el commit original ya fue enviado, la rama remota todavía tiene el ID del commit antiguo. Enviar el commit modificado requiere una actualización forzada:
git push --force-with-lease
Prefiere --force-with-lease sobre --force. Se niega a sobrescribir la rama remota si alguien más envió nuevo trabajo desde tu última extracción.
Limpiar Varios Commits con Rebase Interactivo
El rebase interactivo te permite editar varios commits a la vez. Eliges un rango, luego Git abre una lista de tareas donde puedes elegir, reformular, fusionar, arreglar, reordenar o detenerte en commits.
Para editar los últimos cinco commits:
git rebase -i HEAD~5
Verás una lista como esta:
pick a1b2c3d Agregar script de despliegue
pick b2c3d4e Corregir error tipográfico
pick c3d4e5f Agregar verificación de salud
pick d4e5f6a Actualizar documentación
pick e5f6a7b Ajustar tiempo de espera
Cambia el comando al inicio de cada línea para controlar lo que sucede. Las opciones comunes son:
pick: mantener el commit tal como está.reword: mantener los cambios pero editar el mensaje.squash: combinar este commit con el anterior y editar el mensaje combinado.fixup: combinar este commit con el anterior y descartar el mensaje de este commit.edit: detenerse en este commit para que puedas cambiar su contenido.drop: eliminar el commit.
Por ejemplo, si "Corregir error tipográfico" pertenece a "Agregar script de despliegue," cambia la segunda línea:
pick a1b2c3d Agregar script de despliegue
fixup b2c3d4e Corregir error tipográfico
pick c3d4e5f Agregar verificación de salud
pick d4e5f6a Actualizar documentación
pick e5f6a7b Ajustar tiempo de espera
Guarda y cierra el editor. Git reproduce los commits y combina la corrección del error tipográfico en el commit anterior.
El rebase interactivo también es útil para mejorar los mensajes de los commits antes de una solicitud de extracción. Si tres commits dicen "actualizar," usa reword y conviértelos en mensajes que expliquen el cambio real.
Si aparece un conflicto, resuélvelo como un conflicto de fusión normal:
git status
git add archivo-resuelto
git rebase --continue
Si decides que el rebase no vale la pena:
git rebase --abort
Eso devuelve tu rama al estado anterior al inicio del rebase.
Dividir un Commit Durante el Rebase
A veces un commit contiene dos cambios no relacionados. Por ejemplo, podrías tener un commit que actualiza un manifiesto de Kubernetes y también corrige una sección del README. Esos cambios probablemente deberían estar separados.
Inicia un rebase interactivo:
git rebase -i HEAD~3
Cambia pick a edit para el commit que deseas dividir. Cuando Git se detenga en ese commit, restablécelo mientras mantienes los cambios en tu árbol de trabajo:
git reset HEAD^
Ahora prepara y haz commit de la primera pieza lógica:
git add k8s/deployment.yaml
git commit -m "Actualizar verificación de salud del despliegue"
Luego prepara y haz commit de la segunda pieza:
git add README.md
git commit -m "Documentar comportamiento de verificación de salud"
Continúa el rebase:
git rebase --continue
Esto convierte un commit amplio en dos commits enfocados. Los revisores pueden entender cada cambio sin separar mentalmente el trabajo no relacionado.
Cuándo Pedir Ayuda Antes de Reescribir
Pide ayuda antes de reescribir cualquier rama que otras personas usen. Un líder de equipo, ingeniero de lanzamiento o mantenedor del repositorio puede decirte si la rama es segura para reescribir y cómo maneja el equipo los envíos forzados.
Pide ayuda de inmediato si un rebase afecta commits que ya están desplegados, etiquetados o referenciados por informes de incidentes. En esos casos, preservar el historial suele ser más importante que hacerlo ver ordenado.
Para ramas de características rutinarias, la edición del historial es un paso de limpieza normal. Usa git commit --amend para el último commit, rebase interactivo para una pequeña serie local y --force-with-lease cuando debas actualizar una rama remota que posees.