post thumbnail

Git desde Cero: Reset y Cherry-pick.

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


Detalles del Curso:

Dificultad: Aprendiz

Duración: 10 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 regresar los cambios a un determinado "commit" utilizando git reset y como de como pasar un "commit" específico de una rama a otra utilizando git cherry-pick. Los comandos a utilizar esta semana serán los siguientes:

  • git reset * (varios comandos)
  • git cherry-pick * (varios comandos)

¿Cómo regresar el código fuente a un estado puntual?

En git existen varias maneras para regresar a un estado pasado del proyecto. En este curso hablaremos de tres maneras, "hard", "soft" y "mixed". Si se utiliza "soft" (git reset --soft) para retornar a un punto en específico del proyecto, el mismo lo logra sin disolver el estado actual del proyecto, esto porque no restablece el indice ni la rama de trabajo. Cuando aplicamos este comando todos los archivos pertenecientes a "commits" posteriores a el quedan en "stage" listos para cualquier otra operación que se desee realizar. De forma similar actúa el comando "mixed" (git reset --mixed), la única diferencia con el comando "soft" es que el los cambios no se quedan en "stage". Este es el comando por defecto que usa git cuando no se le asigna una bandera (mixed, soft, hard, etc). De ser necesario retornar completamente a un estado pasado, ignorando todos los "commits" que se encuentren por encima (más nuevos) que este, se utiliza git reset --hard, Este comando particular ignora completamente todos los cambios que hemos realizado ya que restablece el indice y la rama de trabajo al punto donde se encontraban.

Estos tres métodos antes descritos podemos decir que son los "más" populares, ya que a la hora de haber realizado algo realmente errado utilizamos el reset --hard para retornar al estado anterior descartando todo, y cuando realizamos un mal "commit" ya sea porque el mensaje no nos gustó o agregamos muchos archivos en un solo "commit" empleamos reset --soft o reset --mixed.

Hagamos una prueba para observar lo que describimos anteriormente.

$ git lg -6
* 926a59c - albertogg, 31 minutes ago : Archivo de prueba para cherry-pick
*   08bddd4 - albertogg, 2 weeks ago : Merge commit '4f34bfe8efc8f797bac71dfcd736cb7fa14efc42' as 'node_express_subtree'
|\
| * 4f34bfe - albertogg, 2 weeks ago : Squashed 'node_express_subtree/' content from commit 0f81501
* 2614422 - albertogg, 3 weeks ago : Primer commit con un submódulo
* de13f1b - albertogg, 5 weeks ago : Commit planeado. archivo nuevo y viejo
* f2ead5d - albertogg, 6 weeks ago : Referencia en readme.

Nos vamos a devolver hasta el "commit" con el hash "2614422" empleando los tres métodos. Comenzando por el "soft".

$ git reset --soft 2614422d18
$ git status
# On branch master
# Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
#   (use "git pull" to update your local branch)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   cherry-test.md
#   new file:   node_express_subtree/.gitignore
#   new file:   node_express_subtree/app.js
#   new file:   node_express_subtree/package.json

Podemos observar que toda la información que se encontraba en los "commits" de hash "4f34bfe", "08bddd4" y "926a59c" ahora están en el stage nuevamente. Si llegáramos a realizar otro "commit" en este punto cambiaremos el árbol de nuestro proyecto. Ahora probemos con "mixed".

$ git reset --mixed 2614422d18
$ git status
# On branch master
# Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
#   (use "git pull" to update your local branch)
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   cherry-test.md
#   node_express_subtree/
nothing added to commit but untracked files present (use "git add" to track)

Utilizando este comando apreciamos que todo lo que se encotraba en los "commits" de hash "4f34bfe", "08bddd4" y "926a59c" no se descartó pero se encuentra en archivos modificados, pero sin estar en el "stage". Por último encontramos "hard".

$ git reset --hard 2614422d18
HEAD is now at 2614422 Primer commit con un submódulo
$ git status
# On branch master
# Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
#   (use "git pull" to update your local branch)
#
nothing to commit, working directory clean

Aquí podemos observar que tal como lo explicamos anteriormente, se descartan todos los cambios que se encuentran por encima del "commit" que reseteamos.


¿Cómo escoger un "commit" particular de una rama?

Muchas veces cuando estamos trabajando bajo el esquema de ramas, arreglamos un "bug" y seguimos trabajando en una rama que no es la principal (master). Luego queremos que éste arreglo pase a producción (master), pero no podemos unir toda la rama ya que en este momento no nos interesa todo lo que allí se encuentra. Es aquí cuando git cherry-pick entra en acción para extraer únicamente el "commit" que nosotros queremos. Hagamos una prueba del comando:

$ git co -b prueba-pick

Creamos una rama a partir de "master".

$ touch cherry-test.md
$ cat cherry-test.md
# Titulo 1

Archivo de prueba.

Creamos un archivo y le agregamos contenido.

$ git add .
$ git commit -m "Archivo de prueba para cherry-pick"
[prueba-pick 65161e1] Archivo de prueba para cherry-pick
 1 file changed, 3 insertions(+)
 create mode 100644 cherry-test.md

Agregamos al "stash" y realizamos el "commit".

$ git co master
Switched to branch 'master'

Cambiamos de nuevo a la rama principal (master).

$ git cherry-pick 65161e1
[master 926a59c] Archivo de prueba para cherry-pick
 1 file changed, 3 insertions(+)
 create mode 100644 cherry-test.md

En este momento utilizando el hash corto "65161e1" que nos arrojo el commit sobre la rama "prueba-pick", le decimos al commando cherry-pick que nos extraiga dicho "commit" y lo agregue a la rama principal. Ahora, podemos comprobar que se encuentra agregado revisando el log.

$ git lg -4
* 926a59c - albertogg, 16 minutes ago : Archivo de prueba para cherry-pick
*   08bddd4 - albertogg, 2 weeks ago : Merge commit '4f34bfe8efc8f797bac71dfcd736cb7fa14efc42' as 'node_express_subtree'
|\
| * 4f34bfe - albertogg, 2 weeks ago : Squashed 'node_express_subtree/' content from commit 0f81501
* 2614422 - albertogg, 3 weeks ago : Primer commit con un submódulo

De ésta misma manera se puede aplicar el procedimiento para extraer cualquier "commit" particular hacia cualquier rama que se desee. Lo importante es estar ubicado en la rama a la que se le aplicará el "commit" a la hora de ejecutar el git cherry-pick hash.


Conclusión

En este último capítulo y en conjunto con los cursos anteriores hemos adquirido el conocimiento necesario para poder restablecer el proyecto a estados anteriores, ya sea descartando cambios parcial o completamente. También aprendimos a copiar un "commit" particular de una rama a otra sin necesidad de unir las dos ramas. Ciertamente estas herramientas nos pueden llegar salvar de graves problemas, eso si, como consejo, JAMAS utilicen un "reset" sobre cambios que ya se encuentren respaldados en un repositorio remoto. 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