Git reflog: recupera commits perdidos aunque hayas hecho reset o rebase
Si hiciste `git reset --hard`, borraste una rama o un rebase salió mal, no necesariamente perdiste tu trabajo. `git reflog` guarda el historial de movimientos de HEAD y permite recuperar commits que ya no aparecen en el log normal.
Por Equipo Starbyte
Git reflog: recupera commits perdidos aunque hayas hecho reset o rebase
Estás trabajando en una rama, haces varios commits, pruebas un cambio y luego ejecutas algo como:
git reset --hard HEAD~3
De pronto, los últimos commits desaparecen del historial.
O peor: hiciste un rebase, hubo conflictos, abortaste mal el proceso y ahora no encuentras el commit donde estaba tu avance.
Antes de entrar en pánico, hay una herramienta que muchos desarrolladores no usan hasta que la necesitan de verdad:
git reflog
git reflog registra los movimientos recientes de HEAD, ramas y referencias locales. En otras palabras, aunque un commit ya no aparezca en git log, todavía puede estar disponible en el reflog.
Qué problema resuelve git reflog
git log muestra el historial alcanzable desde la rama actual.
Pero si hiciste un reset, borraste una rama o moviste HEAD, algunos commits pueden dejar de aparecer en el log normal.
git reflog permite ver movimientos como:
- Cambios de rama.
- Commits realizados.
- Resets.
- Rebases.
- Merges.
- Checkouts.
- Cambios de posición de
HEAD.
Eso permite recuperar commits que parecen perdidos.
Requisitos previos
Necesitas:
- Tener Git instalado.
- Estar dentro de un repositorio Git.
- Trabajar con un repositorio local donde ocurrió el problema.
- No haber limpiado agresivamente objetos con
git gc --prune=now. - Conocer aproximadamente qué acción causó la pérdida.
Puedes verificar Git con:
git --version
Escenario práctico
Supongamos que tu historial era así:
A---B---C---D---E feature/pagos
Luego ejecutaste:
git reset --hard HEAD~2
Ahora tu rama queda así:
A---B---C feature/pagos
Los commits D y E ya no aparecen en git log.
Pero probablemente sigan disponibles en git reflog.
Paso 1: revisar el reflog
Ejecuta:
git reflog
Verás una salida parecida a:
a1b2c3d HEAD@{0}: reset: moving to HEAD~2
f9e8d7c HEAD@{1}: commit: agregar validación de pagos
e6d5c4b HEAD@{2}: commit: corregir cálculo de comisión
c3b2a1f HEAD@{3}: commit: crear formulario de pagos
La línea importante es la que contiene el commit que quieres recuperar.
En este ejemplo, el commit perdido podría ser:
f9e8d7c
Paso 2: crear una rama de rescate
Nunca recuperes a ciegas sobre tu rama actual.
Primero crea una rama temporal desde el commit encontrado:
git branch rescate-pagos f9e8d7c
Luego cambia a esa rama:
git switch rescate-pagos
Ahora revisa el historial:
git log --oneline --decorate -5
Si tus commits están ahí, ya recuperaste el trabajo.
Paso 3: decidir cómo integrar el rescate
Una vez recuperado el commit, tienes varias opciones.
Opción A: continuar trabajando en la rama de rescate
Si la rama recuperada está bien, puedes seguir desde ahí.
git switch rescate-pagos
Luego haces push:
git push -u origin rescate-pagos
Opción B: llevar un commit específico con cherry-pick
Si solo necesitas un commit, vuelve a tu rama original:
git switch feature/pagos
Y aplica el commit recuperado:
git cherry-pick f9e8d7c
Opción C: comparar antes de integrar
Antes de mezclar cambios, compara:
git diff feature/pagos..rescate-pagos
También puedes ver los commits diferentes:
git log --oneline feature/pagos..rescate-pagos
Caso 1: recuperar después de reset hard
Ejecutaste:
git reset --hard HEAD~1
Solución:
git reflog
git branch rescate HEAD@{1}
git switch rescate
Si HEAD@{1} apunta al estado anterior al reset, tendrás de vuelta tu commit.
También puedes usar directamente el hash:
git branch rescate a1b2c3d
Caso 2: recuperar una rama borrada
Borraste una rama local:
git branch -D feature/reporte
Si estuviste parado en esa rama recientemente, revisa:
git reflog
Busca el último commit asociado a esa rama o al checkout anterior.
Luego recréala:
git branch feature/reporte a1b2c3d
Verifica:
git switch feature/reporte
git log --oneline -5
Caso 3: recuperar después de un rebase problemático
Después de un rebase mal resuelto, puedes buscar el estado anterior.
Ejecuta:
git reflog
Busca una línea similar a:
HEAD@{5}: rebase (start): checkout main
HEAD@{6}: commit: avance antes del rebase
Crea una rama antes del rebase:
git branch antes-del-rebase HEAD@{6}
Luego revisa:
git switch antes-del-rebase
git log --oneline --decorate -10
Si el estado es correcto, puedes repetir el rebase con más cuidado o continuar desde esa rama.
Caso 4: recuperar un commit específico
Si recuerdas el mensaje del commit, puedes combinar reflog con búsqueda.
Primero:
git reflog
Si hay demasiadas líneas, usa:
git reflog --date=iso
También puedes buscar en todos los commits alcanzables y reflog con:
git log -g --oneline --all
Cuando encuentres el hash, crea una rama:
git branch rescate a1b2c3d
Diferencia entre git log y git reflog
| Comando | Qué muestra | Uso principal |
|---|---|---|
git log |
Historial alcanzable desde la rama actual | Ver commits normales |
git reflog |
Movimientos locales de HEAD y referencias | Recuperar estados previos |
git log -g |
Reflog mostrado en formato de log | Buscar commits en reflog |
git fsck --lost-found |
Objetos huérfanos | Último recurso |
Comandos esenciales
Ver reflog:
git reflog
Ver reflog con fechas:
git reflog --date=iso
Crear una rama desde un punto del reflog:
git branch rescate HEAD@{2}
Crear una rama desde un hash:
git branch rescate a1b2c3d
Cambiar a la rama recuperada:
git switch rescate
Aplicar un commit recuperado:
git cherry-pick a1b2c3d
Comparar rama actual con rama recuperada:
git diff main..rescate
Ver commits que existen en rescate y no en main:
git log --oneline main..rescate
Errores comunes
Usar reset otra vez sin crear una rama de rescate.
Primero crea una rama desde el commit encontrado. Es más seguro.
Copiar el hash incorrecto.
Revisa el mensaje del commit y la fecha antes de recuperar.
Pensar que reflog funciona igual en remoto.
El reflog es local. GitHub o GitLab no guardan tu reflog local.
Esperar demasiado tiempo.
Git puede limpiar objetos antiguos con garbage collection. Mientras más pronto actúes, mejor.
Hacer git gc --prune=now después del problema.
Eso puede eliminar objetos que todavía podías recuperar.
Confundir HEAD@{1} con un hash permanente.
HEAD@{1} cambia con el tiempo. Para recuperación importante, usa el hash del commit.
Buenas prácticas
- Antes de un rebase complejo, crea una rama de respaldo.
- Antes de un reset agresivo, guarda el hash actual.
- Usa
git statusantes de ejecutar comandos destructivos. - Prefiere
git switch -c respaldosi tienes dudas. - No borres ramas con
-Dsi no verificaste que fueron mergeadas. - Usa nombres claros para ramas de rescate.
- Después de recuperar, integra con
cherry-picko merge con cuidado. - No ejecutes limpieza agresiva si acabas de perder commits.
Flujo profesional recomendado
Si perdiste commits:
- No hagas más resets.
- Ejecuta
git reflog. - Busca el commit o estado anterior al error.
- Copia el hash correcto.
- Crea una rama de rescate.
- Cambia a esa rama.
- Verifica con
git log. - Compara con tu rama actual.
- Integra con
cherry-pick, merge o continúa desde la rama recuperada. - Elimina la rama de rescate solo cuando estés seguro.
Ejemplo completo
# 1. Ver movimientos recientes
git reflog
# 2. Crear rama desde el estado anterior al error
git branch rescate HEAD@{3}
# 3. Cambiar a la rama recuperada
git switch rescate
# 4. Verificar commits
git log --oneline --decorate -10
# 5. Volver a la rama principal de trabajo
git switch feature/pagos
# 6. Aplicar solo el commit necesario
git cherry-pick a1b2c3d
Idea clave
git reflog es tu historial de movimientos local.
Cuando git log ya no muestra un commit, eso no significa que se perdió para siempre.
Si actúas rápido, buscas el hash correcto y creas una rama de rescate, puedes recuperar trabajo después de un reset --hard, un rebase problemático o una rama borrada.
Antes de repetir el trabajo desde cero, revisa el reflog.