post thumbnail

Git desde Cero: Reflog y Fsck

Publicado Por: Alberto Grespan, El 26/09/2013


Detalles del Curso:

Dificultad: Heroe

Duración: 20 min


Hemos habilitado un repo en GitHub para que puedas descargar el código de esta entrada:

Échale un vistazo aquí.

Bienvenidos a un nuevo capítulo de Git desde cero en este curso hablaremos sobre como recuperar algún "commit" que pudo perderse o ser borrado sin querer cuando modificamos el historial o borramos una rama. Para esto utilizaremos git reflog y como alternativa extrema si por algún motivo no podemos recuperarlo utilizaremos git fsck.


¿Qué es reflog?

Ya sabemos que git nos ayuda a hacer un seguimiento de todos las actualizaciones ("commits") que realizamos. Este mecanismo para realizar el seguimiento de todas las actualizaciones se llama "reflog". la información que recoge el "reflog" viene siendo la "misma" que la del git log, pero presentada de manera diferente ya que es almacenada dentro de la misma carpeta .git/logs/.

Como ya dijimos que "reflog" es el mecanismo para realizar seguimiento de todas las actualizaciones de nuestro proyecto, podemos afirmar en pocas palabras que nos permite visualizar "commits" perdidos. Puede ocurrir, que en algún momento, uno de los "commits" que hemos realizado se pierda, borremos una rama, o simplemente cuando reescribimos el historial de cambios borramos algo no deseado. El "reflog" tiene archivados todos y cada uno de los estados anteriores de una rama y nos permite revertir o ir a cualquier estado anterior del proyecto de ser necesario. Es muy importante tener claro lo que esta herramienta realiza, ya que seguramente la vamos a tener que utilizar en algún momento.

¿Qué se escribe en el reflog?

Cada vez que se acuatiza la cabeza "HEAD" del árbol en que nos encontremos se escribe en el "reflog". Es decir, cada vez que cambiamos de rama, realizamos un "pull", utilizamos un "merge", "rebase", o simplemente agregamos un nuevo "commit", git escribe dentro del "reflog".

¿Cómo se usa?

El "reflog" se utiliza por medio del comando git reflog tiene ciertas banderas como "expire" para expirar datos dentro del "reflog", pero por lo general solo utilizamos el comando normal.

$ git reflog --relative-date
On branch master
926a59c HEAD@{7 days ago}: reset: moving to 926a59cc1c
47fede5 HEAD@{7 days ago}: commit: Prueba del hook
926a59c HEAD@{2 weeks ago}: reset: moving to 926a59c
2614422 HEAD@{2 weeks ago}: reset: moving to 2614422d18
926a59c HEAD@{2 weeks ago}: reset: moving to 926a59c
2614422 HEAD@{2 weeks ago}: reset: moving to 2614422d18
...

Mediante la bandera --relative-date apreciamos una fecha relativa de cuando se realizó el "commit" {7 days ago}, esto nos puede ayudar de cierta manera a orientarnos mejor.

Si necesitan recuperar algo particular a partir de este momento solo deben utilizar el comando git checkout y luego git reset --hard HashDelCommit para recuperar o ir a un estado particular.

Hagamos esta simple prueba, vamos a regresar al "commit" del capítulo 8 de número de13f1b lo vamos a buscar el por mensaje.

$ git reflog --relative-date | grep -i planeado
de13f1b HEAD@{7 weeks ago}: rebase -i (squash): Commit planeado. archivo nuevo y viejo
a735092 HEAD@{7 weeks ago}: commit: Commit planeado. archivo nuevo y viejo

Luego vamos a crear una rama nueva para no afectar el estado actual de nuestra rama principal.

$ git co -b prueba-reflog
Switched to a new branch 'prueba-reflog'

Y por último a ir a ese estado particular.

$ git reset --hard de13f1b
HEAD is now at de13f1b Commit planeado. archivo nuevo y viejo

Este procedimiento es exactamente el mismo que se debe realizar cuando se pierde un "commit", y de querer podemos utilizar git cherry-pick para trasladar el "commit" a la rama que queramos.

¿Qué es fsck?

"Fsck" es esa herramienta que viene a salvarnos la vida cuando creemos que todo está perdido. En sistemas operativos *nix el comando "fsck" es referido a "File System Check" y revisa las inconsistencias del "File System" para comprobar de que no se haya perdido o dañado nada con un apagón repentino o un "crash" de algún programa. En git el comando revisa la integridad de la base de datos interna de git y busca los objetos que no esten apuntados a otro objeto.

Cuando se pierde un "commit" y no tenemos el "reflog" ya sea porque los expiramos en alguna oportunidad o simplemente borramos la carpeta .git/logs el comando git fsck puede ayudarnos a identificar estos "commits" sueltos a los que nosotros nos referimos como perdidos.

¿Cómo se usa?

El "fsck" se utiliza por medio del comando git fsck. Una vez aplicado el comando comienza a revisar la base de datos de git. También podemos utilizar las siguientes banderas --full o --unreachable. "full" realiza una revisión de múltiples carpetas para encontrar todos los objetos posibles. Por otra parte "unreachable" refleja los objetos que existen pero no se pueden encontrar en ningún otro nodo de referencias. Cuando se encuentran aquí es porque probablemente nosotros borramos una rama o "tag" que los contenía.

Vamos a probar los dos comandos y observar las distintas salidas.

$ git fsck --full
Checking object directories: 100% (256/256), done.
dangling blob 43882b2283b87566d08b5307ff3c5e8abd095b6f
dangling commit 4b7347b7514526606484599ee67d7b7abb601a14
dangling blob b4f0de027a1ccdc432ac652052e78e2f53caa1ff
dangling blob bead78cc772d5149ce300480d274d09cf5632368
dangling commit eb15ce2cc60a1829f24442fb14b3e69eb0866580
dangling commit f511b3332361558cff180717868ac208132bb2bf

Ahora aplicamos el --unreachable

$ git fsck --unreachable
Checking object directories: 100% (256/256), done.
unreachable commit 32018436db16348f4d84bb8b40aa394a195c6ded
unreachable blob 43882b2283b87566d08b5307ff3c5e8abd095b6f
unreachable commit 4b7347b7514526606484599ee67d7b7abb601a14
unreachable commit 81d47a325c1a73efe01fb67753ff2c32e0da44c0
unreachable commit a1248a18c03eedac7046bc140d058647aded02ab
unreachable blob b4f0de027a1ccdc432ac652052e78e2f53caa1ff
unreachable blob bead78cc772d5149ce300480d274d09cf5632368
unreachable commit eb15ce2cc60a1829f24442fb14b3e69eb0866580
unreachable commit f511b3332361558cff180717868ac208132bb2bf

Podemos apreciar que entre los dos existen objetos similares y todos tienen un "hash" por lo cual si aplicamos el mismo procedimiento utilizado con el "reflog" vamos a poder retornar dicho "commit" a el historial.

Debemos tener en cuenta que estos objetos que se reflejan no duran para siempre; es muy probable que en algún momento sean eliminados por git si el mismo comienza a correr su gc ("garbage colector") o corremos el comando git gc.


Conclusión

En este último capítulo y en conjunto con los cursos anteriores hemos adquirido el conocimiento necesario para poder recuperar algún "commit" que hayamos podido borrar. Como sugerencia debes tener en cuenta que si esperas demasiado para recuperar un "commit" puede ser demasiado tarde si git ya corrió su recolector de basura, así que si identificas que algo no está bien corre los comandos "reflog" y "fsck" para asegurar de que todo está como debería estar. Te invitamos a revisar la documentación de ambas herramientas. Si te surge algún tipo de duda no te detengas y déjanos un comentario, que gustosamente lo responderemos.

¡Hasta la semana entrante!


¿Te ha gustado esta publicación?

Compártela:

Por Alberto Grespan

Conoce más sobre este autor aquí


comments powered by Disqus