No hay nada más molesto para un desarrollador o ingeniero de datos que borrar ramas de git o restablecer commits por accidente cuando no se quería. Por eso, estoy feliz de compartir algo que aprendí a través de mi propia experiencia y que hubiera deseado aprender antes, que es cómo usar git reflog
. git reflog
es una de esas técnicas que definitivamente vale la pena aprender; si inviertes un poco de tiempo ahora, puedes evitar un gran dolor de cabeza más adelante.
Mientras te mostraré git reflog
, que encuentro realmente útil para navegar y recuperarse de errores, también quiero recomendar nuestros cursos Foundations of Git e Introduction to GitHub Concepts para aprender todo lo que hay que saber sobre control de versiones.
¿Qué es git reflog?
Git reflog, o registro de referencia, es un mecanismo de seguimiento local que registra actualizaciones de las puntas de las ramas y la referencia HEAD en un repositorio de Git. (En el contexto de Git, HEAD se refiere al commit actual en el que se basan tu directorio de trabajo y área de preparación.)
A diferencia de git log
, que muestra el historial de commits basado en ascendencia, mostrando cómo están conectados los commits en una rama, git reflog
captura todos los movimientos de HEAD, incluyendo cambios de ramas, rebases, resets y commits. Esto hace que reflog sea útil para recuperar commits perdidos y depurar acciones recientes.
¿Cuándo se crean las entradas de reflog?
Las entradas del reflog se crean cada vez que realizas acciones que cambian el estado de HEAD o las referencias de las ramas. Escenarios comunes incluyen lo siguiente:
-
Realizar cambios con
git commit
. -
Cambiar a una rama diferente con
git checkout nombre_rama
. -
Crear una nueva rama con
git branch nueva_rama
. -
Hacer un rebase con
git rebase
-
Revertir a un commit anterior con
git reset --hard
. -
Combinar ramas con
git merge
.
Aquí tienes el código que usas para rastrear actualizaciones en el repositorio local:
git reflog
Usando git reflog para rastrear actualizaciones en el repositorio local. Imagen por el Autor.
Cómo interpretar la salida de git reflog?
Puedes interpretar la salida de la siguiente manera:
-
HEAD@{0}
: La acción más reciente fue cambiar a la rama HEAD. -
HEAD@{1}
: Antes de eso, había cambiado un archivo de tipo.xlxs
a formato.csv
. -
HEAD@{2}
: Hice el primer commit al enviar los archivos al repositorio.
Cada entrada muestra:
-
El hash del commit (
fa82776
) -
El índice del reflog (
HEAD@{0}
,HEAD@{1}
, etc.) -
Una descripción de la acción realizada (commit, checkout, rebase)
Cómo usar git reflog
Git reflog proporciona una manera de rastrear actualizaciones de referencias y restaurar los estados anteriores de tu repositorio. Al comprender cómo navegar por las entradas de reflog, puedes recuperar commits perdidos, deshacer cambios y comparar versiones pasadas de tu trabajo.
Comando básico de git reflog
A continuación se muestra el comando básico de reflog:
git reflog
El comando anterior muestra una lista de acciones recientes que actualizaron HEAD o referencias de ramas, incluyendo commits, cambios de rama, resets, rebases y más. Cada entrada está indexada, como HEAD@{0}
y HEAD@{1}
, para representar su posición en la historia de reflog.
Referenciando estados pasados
Git reflog sirve como un registro de actualizaciones de referencias pasadas, lo que nos permite localizar y restaurar puntos anteriores en la historia de nuestro repositorio. Sin él, estas referencias no existirían y necesitaríamos hashes de confirmación exactos para regresar a estados pasados específicos. Ahora, exploremos cómo Git nos permite navegar por estos estados pasados usando git checkout
.
HEAD@{n}
: Se refiere a una entrada específica del reflog, donde n
es el índice. Por ejemplo, HEAD@{2}
se refiere al tercer estado más reciente de HEAD.
git checkout HEAD@{2}
Usando git checkout para rastrear cambios pasados. Imagen por el autor.
branch@{time}
: Se refiere al estado de una rama en un momento específico. Por ejemplo, main@{1.week.ago}
se refiere al estado de la rama principal hace una semana, mientras que feature@{yesterday}
se refiere al estado de la rama de características de ayer.
git checkout main@{1.week.ago}
Usando git checkout para rastrear cambios pasados. Imagen por el autor.
Cualificadores basados en el tiempo
git reflog
no solo nos ayuda a restaurar estados pasados, sino que también nos permite compararlos. Dado que reflog
rastrea actualizaciones de referencias, podemos usarlo para ver cómo ha cambiado nuestro repositorio con el tiempo. Ahora, veamos cómo git diff
utiliza las entradas de reflog para comparar estados pasados y presentes.
A continuación se muestran ejemplos de cualificadores de tiempo que facilitan la restauración de su repositorio a un punto específico en el tiempo en lugar de depender únicamente de los números de índice de reflog.
git checkout HEAD@{1.minute.ago} # Estado de hace un minuto
git checkout HEAD@{1.hour.ago} # Estado de hace una hora
git checkout HEAD@{1.week.ago} # Estado de hace una semana
git checkout HEAD@{yesterday} # Estado desde ayer
git checkout HEAD@{2024-01-01.12:00:00} # Estado en una marca de tiempo específica
Comparando estados pasados con git diff
Puedes comparar estados pasados usando comandos como git diff
. El siguiente comando compara el estado actual de la rama principal main@{0}
con su estado de hace un día, main@{1.day.ago}
. La salida mostrará cualquier diferencia entre estos dos instantáneas.
git diff main@{0} main@{1.day.ago}
Comparando estados pasados con git diff. Imagen por el Autor.
Casos de uso comunes para Git Reflog
Git reflog es una herramienta invaluable para recuperar cambios perdidos, deshacer errores y solucionar errores comunes de Git. A continuación se presentan algunos escenarios prácticos donde git reflog
puede ayudar.
Deshacer un reseteo incorrecto
Si reseteaste accidentalmente tu rama usando git reset --hard
, puedes usar reflog para restaurar tu estado anterior.
git reset --hard HEAD@{3}
Recuperando commits perdidos
Si eliminas accidentalmente una rama o pierdes commits debido a un reset o rebase, puedes encontrar el commit perdido usando git reflog
.
git reflog
Localiza el hash del commit en la salida del reflog y reviértelo:
git checkout <commit-hash>
Una vez que verifiques el commit perdido, puedes crear una nueva rama para preservarlo:
git branch recovered-branch <commit-hash>
Corrigiendo un rebase fallido
Si un rebase sale mal, puedes usar git reflog
para encontrar el commit antes del rebase y resetear tu rama. Identifica el commit antes del rebase y resétalo.
git reset --hard HEAD@{3} # Ajusta el número basado en la salida de reflog
Restaurando una rama eliminada
Si borras accidentalmente una rama, puedes recuperarla usando git reflog
. Encuentra el último commit conocido de la rama eliminada y recriala:
git branch restored-branch <commit-hash>
Seguimiento del historial de stash
Git reflog también se puede usar para ver el historial de stash. El siguiente comando lista las operaciones de stash, permitiéndote recuperar stashes antiguos si es necesario.
git reflog stash
Para aplicar una entrada de stash anterior, utiliza el siguiente comando:
git stash apply stash@{2}
Consulta nuestro Git Pull Forzado: Cómo Sobrescribir una Rama Local con Remota tutorial para aprender las mejores prácticas para sobrescribir cambios locales.
Subcomandos y Opciones de Git Reflog
Git proporciona varios subcomandos y opciones para gestionar e interactuar con los reflogs.
Subcomandos de reflog de Git
A continuación se presenta un desglose estructurado de los principales git reflog
subcomandos y su uso.
git reflog show
: Muestra las entradas de reflog para HEAD por defecto o para una referencia especificada como una rama.
git reflog show
Usando git reflog show para mostrar entradas para una referencia especificada. Imagen por Autor.
git reflog list
: Este comando muestra todas las referencias con un reflog. Es útil para identificar ramas y referencias HEAD con entradas de reflog almacenadas.
git reflog list
git reflog delete <ref>@{<specifier>}
: Elimina las entradas antiguas del reflog que exceden el límite de tiempo especificado. Por ejemplo, el siguiente comando elimina las entradas más antiguas de 30 días.
git reflog expire --expire=30.days.ago
git reflog delete <ref>@{<specifier>}
: Elimina una entrada de reflog particular basada en su referencia y posición. El siguiente comando elimina la entrada de reflog en el índice 2
para HEAD
.
git reflog delete HEAD@{2}
git reflog exists <ref>
: Verifica si existe un reflog para una referencia específica. Por ejemplo, el comando a continuación devuelve éxito si la rama principal tiene un reflog.
git reflog exists main
Opciones para los subcomandos de git reflog
Las siguientes son las opciones disponibles para los subcomandos de git reflog
y su uso.
--expire-unreachable=<time>
: Elimina solo aquellas entradas de reflog que son inalcanzables desde cualquier referencia. Por ejemplo, el comando a continuación elimina las entradas de reflog inalcanzables que tienen más de 7 días.
git reflog expire --expire-unreachable=7.days.ago
--all
: Procesa reflogs para todas las referencias, no solo para HEAD
. El comando a continuación limpia todos los reflogs que tienen más de 60 días en todas las ramas.
git reflog expire --expire=60.days.ago --all
--dry-run
: Simula la ejecución de un comando, mostrando lo que se eliminaría sin borrar realmente nada. Por ejemplo, el comando a continuación muestra qué entradas serían eliminadas.
git reflog expire --expire=30.days.ago --dry-run
--verbose
: Proporciona una salida detallada sobre las acciones realizadas por el comando. El comando a continuación muestra detalles verbosos mientras expira entradas antiguas del reflog.
git reflog expire --expire=90.days.ago --verbose
Git Reflog vs. Git Log: Principales Diferencias
Tanto git log
como git reflog
ofrecen información sobre la historia de un repositorio, pero sirven para diferentes propósitos. Veamos estas diferencias para entender cómo cada uno puede ser utilizado para el control de versiones y estrategias de recuperación.
-
git log
muestra el historial de commits siguiendo la ascendencia de los commits en una rama. Proporciona una vista cronológica de cómo ha evolucionado el contenido del repositorio. -
git reflog
registra actualizaciones a referencias como HEAD, ramas y alijos, incluyendo acciones como cambios de rama, reinicios, rebase y más. Realiza un seguimiento de cambios que pueden no ser parte de la ascendencia de confirmaciones. -
git reflog
es estrictamente local en tu máquina y no se comparte con repositorios remotos. -
Mientras que
git log
no puede recuperar commits que ya no son parte de la genealogía de la rama,git reflog
puede ayudar a recuperar commits “perdidos” rastreando actualizaciones de referencia, incluso si esos commits ya no son accesibles desde ninguna rama.
La tabla a continuación resume estas diferencias clave.
Feature | git log | git reflog |
---|---|---|
Rastrea commits | Sí | No |
Rastrea actualizaciones de referencia | No | Sí |
Compartido en remoto | Sí | No |
Puede recuperar commits perdidos | No | Sí |
Mejores prácticas para usar Git Reflog
Git reflog es una herramienta poderosa para recuperar commits perdidos y solucionar problemas de historial, pero usarla efectivamente requiere precaución. Aquí hay algunas mejores prácticas a seguir al trabajar con reflog.
-
Usar Reflog para Recuperación y Depuración: Si reseteó o rehizo incorrectamente una rama por accidente, verifique
git reflog
para encontrar una referencia anterior y restaurarla. -
Tenga cuidado con
git reset --hard
:git reset --hard
puede eliminar permanentemente los cambios no confirmados. Siempre verifique primero el reflog para asegurarse de que pueda recuperar si algo sale mal. -
Haga copias de seguridad antes de ejecutar comandos destructivos: Para protegerse contra la pérdida de datos, implemente copias de seguridad automatizadas de sus repositorios de Git. Siempre almacene las copias de seguridad en un lugar seguro y fuera del sitio para garantizar la recuperabilidad en caso de falla de hardware u otros desastres.
-
No Te Fíes Únicamente de Reflog para Recuperaciones a Largo Plazo:Por defecto, las entradas de reflog se mantienen durante 90 días. Después de este período, pueden ser eliminadas y volverse irrecuperables. Envía regularmente tus commits a un repositorio remoto para asegurarte de que se preserven más allá de tu reflog local.
-
Usa
git reflog expire
para gestionar las entradas antiguas: Si el reflog de tu repositorio se vuelve desordenado, elimina las entradas antiguas o inaccesibles usandogit reflog expire
.
Conclusión
Gestionar eficazmente el historial de un proyecto en Git requiere más que solo comandos básicos. Explorar herramientas avanzadas que rastrean actualizaciones de referencia puede proporcionar una red de seguridad valiosa para recuperar commits perdidos, restaurar ramas eliminadas y corregir errores. Obtener experiencia práctica con estas herramientas, junto con comandos como git reset
, git checkout
y git revert
, puede mejorar significativamente tu competencia en el control de versiones.
Tomar nuestros cursos no solo es una excelente manera de aprender, sino que también es una excelente forma de señalar a los empleadores que te tomas en serio el desarrollo de software. Con ese fin, recomiendo estudiar nuestra publicación de blog Top 20 Preguntas y Respuestas de Entrevista de Git para Todos los Niveles y realizar nuestra nueva pista de habilidades Git Fundamentals para convertirte en un experto en todo lo relacionado con Git.