Reflog y recuperación de commits perdidos
Aprende a utilizar git reflog para rastrear cambios en tu repositorio y recuperar commits aparentemente perdidos después de operaciones como reset, rebase o branch deletion.
Cristian Escalante
Última actualización: 2 de mayo de 2025
Reflog y recuperación de commits perdidos
Una de las características más poderosas pero menos conocidas de Git es su capacidad para recuperar trabajo que parece haberse perdido. Ya sea que hayas hecho un git reset --hard
por error, un rebase que salió mal, o eliminado una rama sin fusionar, Git proporciona herramientas para ayudarte a recuperar tu trabajo. La más importante de estas herramientas es el reflog.
¿Qué es el reflog?
El reflog (registro de referencias) es un mecanismo que Git utiliza para registrar actualizaciones a las puntas de las ramas y otras referencias. Cada vez que la referencia HEAD cambia (por ejemplo, cuando haces checkout a otra rama, commit, reset, etc.), Git registra esa información en el reflog.
A diferencia del historial normal de commits que puedes ver con git log
, el reflog es:
- Local: Solo existe en tu repositorio local y no se comparte al hacer push
- Temporal: Las entradas del reflog tienen una vida limitada (por defecto, 90 días)
- Completo: Registra todas las acciones, incluso aquellas que parecen destructivas
Visualizando el reflog
Para ver el reflog, simplemente ejecuta:
git reflog
La salida se verá algo así:
734713b (HEAD -> main) HEAD@{0}: commit: Add feature X
a6f4612 HEAD@{1}: commit: Update documentation
ebfd14d HEAD@{2}: checkout: moving from feature/test to main
2c4f36d HEAD@{3}: commit: Add test feature
7289f23 HEAD@{4}: reset: moving to HEAD~1
982fb40 HEAD@{5}: commit: Add feature that was later discarded
Cada entrada incluye:
- Un identificador de commit
- Una notación
HEAD@{n}
que indica la posición en el reflog - La acción que causó el cambio
- Una breve descripción
Casos comunes de pérdida de commits
1. Reset duro accidental
Si has hecho un git reset --hard
y perdido commits:
# Situación: acabas de hacer un reset duro y perdiste commits
git reset --hard HEAD~3 # Oops! Perdiste 3 commits
# Solución: usa reflog para ver los commits recientes
git reflog
# Recupera el estado anterior al reset
git reset --hard HEAD@{1} # O usa el hash del commit
2. Rebase que salió mal
Si un rebase causó problemas y quieres volver al estado anterior:
# Situación: un rebase complicado salió mal
git rebase -i main # Algo salió mal durante el rebase
# Solución: aborta el rebase si aún está en progreso
git rebase --abort
# O si ya terminó, usa reflog para volver al estado anterior
git reflog
git reset --hard HEAD@{5} # Donde HEAD@{5} es el estado antes del rebase
3. Rama eliminada accidentalmente
Si eliminaste una rama sin fusionar sus cambios:
# Situación: eliminaste una rama por error
git branch -D feature/importante # Oops!
# Solución: encuentra el último commit de esa rama en el reflog
git reflog
# Crea una nueva rama en ese commit
git branch feature/recuperada a6f4612 # Usando el hash del último commit de la rama
4. Commit amend accidental
Si sobrescribiste un commit con --amend
y quieres recuperar la versión original:
# Situación: modificaste el último commit con amend
git commit --amend # Cambió el commit original
# Solución: encuentra el commit original en el reflog
git reflog
git reset --hard HEAD@{1} # La versión antes del amend
Comandos avanzados de reflog
Ver el reflog de una rama específica
git reflog show main
Ver el reflog con más detalles
git reflog --date=iso
Ver el reflog con las diferencias
git reflog -p
Recuperación de commits huérfanos
Los commits "huérfanos" son aquellos que no están conectados a ninguna rama o etiqueta. Pueden crearse por varias razones, como rebase, reset, o eliminación de ramas.
Encontrar commits huérfanos
# Muestra todos los commits, incluyendo los huérfanos
git fsck --lost-found
Este comando mostrará "dangling commits" (commits huérfanos) que podrías querer recuperar.
Examinar un commit huérfano
# Ver el contenido de un commit huérfano
git show <hash-del-commit>
Recuperar un commit huérfano
# Crear una rama apuntando al commit huérfano
git branch recuperado <hash-del-commit>
Estrategias de prevención
Aunque el reflog es una red de seguridad excelente, es mejor prevenir que curar:
1. Crear ramas antes de operaciones arriesgadas
# Antes de un rebase o reset
git branch backup/antes-de-rebase
2. Usar stash para guardar cambios temporales
# Guardar cambios no confirmados
git stash save "Cambios importantes antes de experimento"
3. Hacer commits frecuentes
Los cambios confirmados son mucho más fáciles de recuperar que los no confirmados.
4. Usar reset --soft o --mixed en lugar de --hard
# En lugar de --hard, que descarta cambios
git reset --soft HEAD~1 # Mantiene los cambios en staging
git reset --mixed HEAD~1 # Mantiene los cambios en working directory
Limitaciones del reflog
Es importante entender que el reflog tiene algunas limitaciones:
- Es local: No se transfiere a repositorios remotos
- Es temporal: Las entradas más antiguas de 90 días se eliminan automáticamente
- No incluye archivos no rastreados: Los archivos nuevos que nunca fueron añadidos a Git no se pueden recuperar
- Se limpia con garbage collection:
git gc
puede eliminar entradas del reflog
Configuración del reflog
Puedes ajustar la configuración del reflog según tus necesidades:
# Cambiar el tiempo de expiración del reflog (por ejemplo, a 180 días)
git config --global gc.reflogExpire "180 days"
# Cambiar el tiempo de expiración para referencias no alcanzables
git config --global gc.reflogExpireUnreachable "30 days"
Flujos de trabajo de recuperación
Escenario 1: Recuperar después de un reset duro
# 1. Identifica lo que se perdió
git reflog
# 2. Examina los cambios perdidos
git show HEAD@{1}
# 3. Recupera todo el estado anterior
git reset --hard HEAD@{1}
# O crea una rama para revisar los cambios
git branch recuperacion HEAD@{1}
Escenario 2: Recuperar commits específicos después de un rebase
# 1. Encuentra los commits perdidos
git reflog
# 2. Cherry-pick los commits específicos que necesitas
git cherry-pick abc1234
# 3. O crea una rama temporal con el estado anterior
git branch temp-recuperacion HEAD@{5}
Escenario 3: Recuperar una rama eliminada
# 1. Encuentra el último commit de la rama
git reflog | grep 'nombre-de-rama'
# 2. Crea una nueva rama en ese commit
git branch nueva-rama abc1234
Herramientas complementarias
Git fsck
# Verificar la integridad del repositorio y encontrar objetos huérfanos
git fsck --full
Git gc
# Limpiar objetos innecesarios (¡cuidado! puede eliminar algunos objetos recuperables)
git gc
Git prune
# Eliminar objetos huérfanos (¡usar con extrema precaución!)
git prune
Conclusión
El reflog de Git es una herramienta invaluable para recuperar trabajo que parece haberse perdido. Funciona como una red de seguridad que registra todos los cambios en tu repositorio local, permitiéndote volver a estados anteriores incluso después de operaciones aparentemente destructivas.
Aunque es reconfortante saber que Git proporciona estas capacidades de recuperación, la mejor estrategia es siempre trabajar de manera que minimice la necesidad de usarlas. Hacer commits frecuentes, usar ramas para experimentos y comprender completamente los comandos antes de ejecutarlos te ayudará a evitar situaciones donde necesites recurrir al reflog.
Sin embargo, los errores ocurren, y cuando lo hacen, el reflog puede ser tu mejor aliado para recuperar tu trabajo y seguir adelante.