Introducción
Aprende cómo Git reescribe la historia con git commit --amend, git reflog y git rebase: qué hace cada comando, cuándo usarlo y cómo hacerlo de forma segura.
En Git, la historia es la secuencia de commits que registra cómo cambió tu proyecto a lo largo del tiempo. Cada commit se identifica por un hash único y apunta al commit (o commits) que le precedieron. La mayor parte del tiempo solo agregas a esa cadena. Pero a veces necesitas cambiar lo que ya está ahí — corregir un error tipográfico en un mensaje de commit, combinar varios commits desordenados en uno limpio, o recuperar trabajo que creías haber perdido.
Para esto sirven las herramientas de reescritura de historia de Git. Las tres a las que recurrirás con más frecuencia son:
git commit --amend— reemplaza el commit más reciente.git reflog— muestra cada posición a la que ha apuntadoHEAD, para que puedas recuperar commits "perdidos".git rebase— repite una serie de commits sobre una nueva base, editándolos opcionalmente en el proceso.
Esta página te ofrece una visión general de cada uno. Los capítulos más detallados enlazados arriba recorren el conjunto completo de opciones.
La regla de oro de la reescritura de historia: nunca reescribas commits que ya hayas enviado a una rama compartida. Reescribir cambia los hashes de los commits, por lo que cualquiera que haya descargado los commits anteriores tendrá conflictos. Reescribe libremente en tus ramas locales; deja intacta la historia compartida.
Cambiar el último commit con git commit --amend
Es fácil olvidarse de agregar un archivo al área de preparación, dejar un error tipográfico en un mensaje de commit, o hacer un commit demasiado pronto. En lugar de añadir un commit de "arreglo" separado, git commit --amend te permite reemplazar el último commit por uno corregido.
Para corregir solo el mensaje del commit más reciente:
git commit --amend -m "Add login validation"Para añadir un archivo olvidado al último commit, primero agrégalo al área de preparación y luego realiza el amend sin cambiar el mensaje:
git add forgotten-file.js
git commit --amend --no-editLa opción --no-edit mantiene el mensaje existente y lo reutiliza. En segundo plano, amend no edita el commit antiguo en su lugar — crea un commit completamente nuevo (con un nuevo hash) y mueve la rama para que apunte a él. El commit original queda atrás, sin referencia.
Como el amend produce un nuevo hash, la misma regla de oro aplica: solo realiza amend en un commit que no hayas enviado a una rama que otras personas compartan.
Para una guía completa, consulta git commit --amend.
Recuperar commits perdidos con git reflog
El reflog (registro de referencias) registra cada cambio en el extremo de tus ramas y en HEAD — cada commit, checkout, reset, merge y rebase. Este es tu red de seguridad: incluso después de una reescritura o un reset hard, los commits antiguos siguen estando en el repositorio y el reflog recuerda dónde estaban.
Consulta el registro con:
git reflogUna salida típica tiene este aspecto:
a1b2c3d HEAD@{0}: commit: Add login validation
9f8e7d6 HEAD@{1}: reset: moving to HEAD~1
4c3b2a1 HEAD@{2}: commit: Work in progressCada entrada muestra un hash de commit, una referencia HEAD@{n} (cuántos movimientos atrás) y lo que ocurrió. Si accidentalmente eliminaste un commit con un reset, encuéntralo en el reflog y recupéralo:
git reset --hard HEAD@{2}El comando git reflog también tiene subcomandos como git reflog show, git reflog expire y git reflog delete. Ten en cuenta que las entradas del reflog son locales a tu repositorio y caducan con el tiempo (90 días por defecto para las entradas alcanzables), por lo que son una herramienta de recuperación, no una copia de seguridad permanente. Consulta git reflog y el capítulo relacionado git reset para más detalles.
Reorganizar sobre una nueva base con git rebase
git rebase toma una serie de commits y los repite sobre un commit base diferente. Su principal beneficio es una historia lineal y legible: en lugar de un commit de merge que une dos ramas, tu trabajo aparece como una línea limpia de commits.
Hay dos modos:
- El modo estándar aplica los commits de tu rama actual sobre el extremo de otra rama. Esta es la alternativa al merge al integrar actualizaciones desde
main:
git rebase main- El modo interactivo te permite reordenar, editar, combinar o eliminar commits mientras se repiten. Añade la opción
-iy pasa el commit sobre el que quieres reorganizar:
git rebase -i <base-branch>Un objetivo interactivo habitual son "los últimos N commits", por ejemplo los últimos tres:
git rebase -i HEAD~3Para un tratamiento más completo, consulta git rebase y git rebase interactive.
Editar commits durante un rebase interactivo
Cuando inicias un rebase interactivo, Git abre un editor que lista los commits seleccionados, cada uno precedido por una acción. Cambias la palabra clave de la acción para controlar lo que sucede:
pick— mantiene el commit tal como está (el valor predeterminado).reword(r) — pausa para reescribir el mensaje de ese commit.squash(s) — fusiona este commit con el anterior y combina sus mensajes en un editor.fixup(f) — comosquash, pero descarta el mensaje de este commit y conserva solo el del anterior (sin prompt del editor).edit(e) — hace una pausa para que puedas modificar el contenido del commit.drop(d) — elimina el commit por completo.
Una lista de tareas típica de rebase tiene este aspecto:
pick a1b2c3d Add login form
squash 9f8e7d6 Fix typo in label
fixup 4c3b2a1 Adjust spacingAquí el segundo y el tercer commit se fusionan en el primero, dando como resultado un único commit ordenado.
Por qué los commits reescritos obtienen nuevos IDs
El rebase no mueve los commits originales — crea commits nuevos con los mismos cambios pero diferentes padres y, por tanto, diferentes hashes. Los commits antiguos quedan sin referencia (aún recuperables a través del reflog por un tiempo). Incluso los commits marcados con pick obtienen nuevos IDs si algún commit anterior a ellos en la secuencia fue modificado, porque su padre cambió.

Esta es exactamente la razón por la que la regla de oro importa: los nuevos hashes significan una historia divergente para cualquiera que tuviera los antiguos.