git reflog

En esta página se proporciona un análisis pormenorizado sobre el comando git reflog. Git realiza el seguimiento de las actualizaciones en el extremo de las ramas a través de un mecanismo denominado registros de referencias o "reflogs". Muchos de los comandos de Git aceptan un parámetro para especificar una referencia o "ref", que es un puntero a una confirmación. Entre los ejemplos habituales se incluyen los siguientes:

  • git checkout
  • git reset
  • git merge

Los registros de referencias realizan un seguimiento de cuándo se han actualizado las referencias de Git en el repositorio local. Además de los registros de referencias del extremo de la rama, se conserva un registro de referencias especial para "git stash". Los registros de referencias se almacenan en los directorios dentro del directorio .git del repositorio local. Los directorios de git reflog se encuentran en .git/logs/refs/heads/., .git/logs/HEAD y también en .git/logs/refs/stash si se ha usado el comando git stash en el repositorio.

Hemos explicado git reflog a grandes rasgos en la página Reescritura del historial. En este documento se tratarán los siguientes temas: opciones de configuración ampliadas de git reflog, casos de uso y peligros habituales de git reflog, cómo deshacer los cambios con git reflog, etc.

Uso básico

El caso de uso más básico de Reflog invoca lo siguiente:

git reflog

Se trata básicamente de un acceso directo que equivale a:

git reflog show HEAD

Esto dará como resultado el registro de referencias para HEAD. El resultado debería ser algo parecido a lo siguiente:

eff544f HEAD@{0}: commit: migrate existing content
bf871fd HEAD@{1}: commit: Add Git Reflog outline
9a4491f HEAD@{2}: checkout: moving from main to git_reflog
9a4491f HEAD@{3}: checkout: moving from Git_Config to main
39b159a HEAD@{4}: commit: expand on git context 
9b3aa71 HEAD@{5}: commit: more color clarification
f34388b HEAD@{6}: commit: expand on color support 
9962aed HEAD@{7}: commit: a git editor -> the Git editor

Visita la página Reescritura del historial para ver otro ejemplo de acceso habitual al registro de referencias.

Referencias de reflog

De forma predeterminada, git reflog generará el registro de referencias de la referencia HEAD. HEAD es una referencia simbólica a la rama que está activa actualmente. Los registros de referencias también están disponibles para otras referencias. La sintaxis para acceder a una referencia de Git es name@{qualifier}. Aparte de a las referencias de HEAD, también se puede hacer referencia a otras ramas, etiquetas, repositorios remotos y al stash de Git.

Puedes obtener un "reflog" de todas las referencias mediante el uso de:

  git reflog show --all 

Para ver el registro de referencias de una rama concreta, transmite el nombre de dicha rama a git reflog show.

 git reflog show otherbranch 9a4491f otherbranch@{0}: commit: seperate articles into branch PRs 35aee4a otherbranch{1}: commit (initial): initial commit add git-init and setting-up-a-repo docs 

Al ejecutar este ejemplo, se muestra un registro de referencias de la rama otherbranch. En el siguiente ejemplo, presuponemos que has guardado algunos cambios anteriormente en un stash mediante el comando git stash.

 git reflog stash 0d44de3 stash@{0}: WIP on git_reflog: c492574 flesh out intro 

Esto dará como resultado un registro de referencia para "git stash". Los punteros de referencia que se obtienen se pueden transmitir a otros comandos de Git:

 git diff stash@{0} otherbranch@{0} 

Al ejecutarlo, este código de ejemplo mostrará el resultado de comparación de Git comparando los cambios de stash@{0} con la referencia otherbranch@{0}.

Registros de referencia programados

Todos los registros de referencias cuentan con marcas de fecha y hora asignadas a ellos. Estas marcas de fecha y hora se pueden aprovechar como token qualifier de la sintaxis del puntero de referencia de Git. Esto permite filtrar los registros de referencias de Git por tiempo. A continuación, se muestran algunos ejemplos de calificadores de tiempo:

  • 1.minute.ago
  • 1.hour.ago
  • 1.day.ago
  • yesterday
  • 1.week.ago
  • 1.month.ago
  • 1.year.ago
  • 2011-05-17.09:00:00

Los calificadores de tiempo se pueden combinar (p. ej., 1.day.2.hours.ago). Además, se aceptan las formas en plural (p. ej., 5.minutes.ago).

Las referencias de los calificadores de tiempo se pueden transmitir a otros comandos de Git.

  git diff main@{0} main@{1.day.ago} 

En este ejemplo, se establece la diferencia entre la rama principal actual y la rama principal de hace 1 día. Esto resulta muy útil si quieres saber los cambios que se han producido en un plazo de tiempo.

Subcomandos y opciones de configuración

git reflog acepta algunos argumentos de adición que se consideran subcomandos.

Show - git reflog show

show se usa implícitamente de forma predeterminada. Por ejemplo, el comando:

 git reflog main@{0} 

es equivalente al comando:

 git reflog show main@{0} 

Además, git reflog show es un alias de git log -g --abbrev-commit --pretty=oneline. Al ejecutar git reflog show se mostrará el registro para el que se ha usado.

Expire - git reflog expire

El subcomando "expire" limpia entradas antiguas o inaccesibles del registro de referencias. expire puede ocasionar una pérdida de datos. Los usuarios finales no suelen emplear este subcomando, pero Git sí lo utiliza internamente. Al usar una opción -n o --dry-run para git reflog expire, se llevará a cabo un simulacro que dará como resultado las entradas de referencia de registro que se han marcado para eliminar, pero no llegará a eliminarlas.

De forma predeterminada, la fecha de caducidad del registro de referencias se fija al cabo de 90 días. Se puede especificar un plazo de caducidad empleando un argumento de línea de comandos --expire=time en git reflog expire o definiendo un nombre de configuración de Git de gc.reflogExpire.

Delete - git reflog delete

El subcomando delete es bastante transparente: simplemente elimina la entrada de registro de referencias usada. Al igual que sucede con el comando expire, delete puede causar la pérdida de datos y no suelen invocarlo los usuarios finales.

Recuperación de las confirmaciones perdidas

En realidad, en Git nunca se pierde nada, aunque se lleven a cabo operaciones de reescritura del historial, como la fusión mediante cambio de base o la corrección de confirmaciones. En el siguiente ejemplo, vamos a suponer que hemos realizado algunos cambios nuevos en nuestro repositorio. Nuestro ejemplo de git log --pretty=oneline tendrá el siguiente aspecto:

 338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content 1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content c49257493a95185997c87e0bc3a9481715270086 flesh out intro eff544f986d270d7f97c77618314a06f024c7916 migrate existing content bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

Confirmaremos dichos cambios y realizaremos lo siguiente:

 #make changes to HEAD git commit -am "some WIP changes" 

Con la incorporación de la nueva confirmación, el registro tendrá el siguiente aspecto:

 37656e19d4e4f1a9b419f57850c8f1974f871b07 some WIP changes 338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content 1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content c49257493a95185997c87e0bc3a9481715270086 flesh out intro eff544f986d270d7f97c77618314a06f024c7916 migrate existing content bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

En este punto, realizamos una fusión interactiva mediante cambio de base de la rama principal al ejecutar…

 git rebase -i origin/main 

Durante la fusión mediante cambio de base, marcamos las confirmaciones para combinarlas con el subcomando de fusión mediante cambio de base s. Además, combinamos algunas confirmaciones en la confirmación "some WIP changes" más reciente.

Al combinar las confirmaciones, el resultado de git log tendrá el siguiente aspecto:

 40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs some WIP changes 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs 

Si examinamos git log en este punto, parecerá que ya no tenemos las confirmaciones que se marcaron para su combinación. ¿Y si queremos actuar en una de las confirmaciones combinadas? ¿Tal vez para eliminar sus cambios del historial? Esta es una oportunidad para utilizar el comando "reflog".

 git reflog 37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog 37656e1 HEAD@{1}: rebase -i (start): checkout origin/main 37656e1 HEAD@{2}: commit: some WIP changes 

Podemos ver que hay entradas de registro de referencias para el principio y el final de rebase, y antes de ellas se encuentra nuestra confirmación "some WIP changes". Podemos transmitir la referencia de registro de referencias a git reset y restablecerla a una confirmación anterior a la fusión mediante cambio de base.

 git reset HEAD@{2} 

Al ejecutar este comando de restablecimiento, se moverá HEAD a la confirmación en la que se añadió "some WIP changes", con lo que, básicamente, se restaurarán el resto de las confirmaciones combinadas.

Resumen

En este tutorial, hemos analizado el comando git reflog. A continuación, exponemos algunos temas clave que se han tratado:

  • Cómo consultar el registro de referencias para ramas concretas
  • Cómo deshacer una fusión mediante cambio de base de Git a través del registro de referencias
  • Cómo especificar y ver entradas del registro de referencias basadas en el tiempo

Hemos mencionado brevemente que git reflog se puede usar con otros comandos de Git como git checkout, git reset y git merge. Obtén más información sobre ellos en sus respectivas páginas. Para más información sobre "refs" y "reflog", consulta aquí.

¿Quieres aprender a usar Git?

Prueba este tutorial interactivo.

Comienza ahora