IronWoods.es

Desarrollo web

Blog / Git / Viaje en el tiempo

En ocasiones hay que moverse en el histórico de Git. Podemos ir a un momento pasado como si todos los cambios posteriores nunca hubieran existido, y de echo pueden dejar de hacerlo... Podemos ir atrás a mirar o podemos ir atrás a cambiar algo para luego volver al punto de partida, pero cuidado, pisar una mariposa en el Jurásico puede borrar tu existencia.

Un caso real...

Cuando saque la versión 0.4.20 de la aplicación TaskTimer tenía un bug muy grave y durante unas horas se distribuyó con él. Al detectarlo lo arregle enseguida, pero aparecieron otros fallos... había que redistribuir una versión anterior estable, y arreglar lo que fallaba antes de incorporar la última "feature".

Para salir del paso tenía que volver atrás en el histórico, recompilar y sustituir el fichero que estaba siendo distribuido.

¿Cómo volver a una versión anterior?

Por suerte, sabía en qué parte del código introduje el bug y que había sido en uno de los 3 últimos commits (el último en realidad). Entonces si estaba en la versión 0.4.20, había que volver a la 0.4.13 que era justo el commit precedente.


Primero hice un stash, porque estaba editando varios ficheros.

git stash


Luego tenía ver los últimos mensajes de commit, para tener sus "hash".

git log --oneline -3


Y como resultado:

2336012 (HEAD -> develop, origin/develop) 17.09.2018 - 0.4.20 Added asc order in tasks and projects

c953c5f 17.09.2018 - 0.4.13 Capitalizes first letters (names, descriptions and notes)

911ef25 15.09.2018 - 0.4.12 Refactorized "KeyInteractivityHandler"


El último commit tiene el hash 2336012 la rama es develop.

Para ir a la versión 0.4.13, use el comando:

git checkout c953c5f


Si antes la consola mostraba:

Io@PC MINGW64 ~TaskTimer/src/tasktimer (develop)

$


trás el comando:

Io@PC MINGW64 ~TaskTimer/src/tasktimer ((c953c5f...))

$


Comprobé cuál era el último commit:

git log --oneline -1


Apareció:

c953c5f (HEAD) 17.09.2018 - 0.4.13 Capitalizes first letters (names, descriptions and notes)


En este punto compile y ejecute la aplicación y me dí cuenta de que mostraba la versión 0.4.10. Esto lo indico en una propiedad de la clase principal, de "cuando en cuando"... Puse la actual: 0.4.13, recompilé y redistribuí esta versión. Seguidamente añadí esta "pequeña actualización" al repositorio:

git add MiClase.java

git commit --amend


Se abre el editor (nano en mi caso). Hay que salir sin cambiar nada.

Teclas: Ctrl + X


Y se puede volver al punto de inicio con:

git checkout develop


Se puede tratar de enviar el cambio realizado en el commit anterior al remoto (cuidado con estas cosas si el repo es compartido):

git push -f


El resultado es que... ¿no hay cambios que enviar? No, los repositorios están sincronizados, git no va a enviar nada.

Lo que ha pasado es que la clase con la versión 0.4.13 no fue incorporada "realmente". Hicimos un viaje al pasado en modo "espectador"

Si vuelvo a ese commit, en mi histórico local, el cambio no está.

El método empleado, fue válido para volver atrás, compilar la aplicación a partir del código que tenía en ese momento, pero no, para cambiar el código y volver al principio, y esto es en realidad algo que nunca se debería hacer, si peor que cambiar el histórico de mensajes, pero... !quiero cambiar esa versión¡.

Bien, desde el punto de partida. Volveré atrás, un sólo commit, está vez moviendo el puntero (HEAD):

git reset HEAD~1


Este comando en realidad deshace el último commit, por lo que veremos los ficheros que incluía en el "working area". Ignoré estos ficheros, hice el cambio que quería y actualicé el repositorio:

git add MiClase.java

git commit --amend


Hay que volver al punto de inicio:

git reset ORIG_HEAD


Ahora, al revisar el código, la versión se encuentra correctamente guardada.

Pueden enviarse los cambios al remoto y "recuperar" los ficheros en los que se estaba trabajando:

git push -f

git stash apply

Resumen

Podemos "visitar" commits pasados para:

1. Revisar su contenido.

2. Introducir cambios.

En ambos casos, lo primero que tenemos que hacer es limpiar el área de trabajo y obtener el hash del commit que vamos a visitar, p.e. c953c5f.


Procedimiento para revisar.

Ir al commit:

git checkout c953c5f


Revisar. Volver al inicio:

git checkout nombre_rama


Procedimiento para cambiar.

Cuidado con esto, tendremos problemas si la parte a cambiar se modificó posteriormente.

git reset --soft c953c5f


o bien, si queremos indicar un número de commits hacia atrás:

git reset HEAD~1


Los métodos anteriores, trabajan de forma diferente. A primera vista el primero sólo mueve el puntero, el segundo además nos informa de los ficheros aun no commiteados:

Io@PC MINGW64 ~/Desktop/test-git (develop)

$ git reset HEAD~1

Unstaged changes after reset:

...

Si probáramos ambos métodos y comprobáramos el estado (git status) podríamos obtener resultados bastante diferentes.

Para evitarnos problemas no debemos tocar ficheros que se encuentren en el working o staging area.


Ver cuál es el último commit (el que vamos a cambiar):

git log -1 --oneline


Cambiar. Añadir y guardar en el commit usando ammend:

git add MyFile.xxx

git commit --amend


Volver al punto de partida:

git reset ORIG_HEAD

Referencias:

Gran Maestría en Git

¿Cómo revertir un commit usando el hash?


18-09-2018 (actualizado 23/09/2018)

article>

Entradas relacionadas:

Sitio libre de scripts. Solo efectos HTML / CSS