Aprende a usar Git con Bitbucket Cloud

Aprende cómo deshacer los cambios en Git utilizando Bitbucket Cloud

Objetivo

Aprende cómo deshacer cambios en tu máquina local y en un repositorio de Bitbucket Cloud mientras colaboras con otros.

Resumen de la misión

Comandos cubiertos en este tutorial: git revert, git reset, git log y git status

 

Duración Público Requisitos previos

40 minutos

En este tutorial, se asume que el usuario está familiarizado con los siguientes comandos de git:

git clone, git commit, git pull y git push
Tienes Git instalado
    Tienes una cuenta de Bitbucket

Todo el mundo comete errores. No todos los envíos son perfectos, por lo que este tutorial te ayudará a utilizar las funciones de git más habituales para deshacer un cambio o cambios de forma segura.

En este tutorial, se asume que el usuario está familiarizado con los siguientes comandos de git:

Si no conoces estos comandos, lee primero el artículo Aprende git con Bitbucket Cloud. A continuación, vuelve aquí y aprende cómo deshacer cambios. Estos comandos de git son aplicables a entornos de Windows o Unix. En este tutorial, utilizaremos utilidades de la línea de comandos de Unix al explicar la navegación por el sistema de archivos.

Cómo deshacer cambios en tu máquina local

Cuando el cambio que quieres deshacer está en tu sistema local y no se ha enviado a un repositorio remoto, hay dos formas principales de deshacerlo:

Comando Definición

git revert

Es un comando para "deshacer", pero no en el sentido tradicional. En lugar de eliminar la confirmación, resuelve cómo invertir los cambios introducidos por la confirmación y añade una nueva con el contenido inverso resultante. Así, se evita que Git pierda información en el historial, lo cual resulta importante para la integridad del historial de revisiones y para que la colaboración sea fiable.

git reset

Un comando versátil de git que deshace cambios. El comando git reset tiene un conjunto potente de opciones, pero en este tutorial solo utilizaremos los siguientes modos de restablecimiento:

  • --soft: solo restablece el HEAD a la confirmación que selecciones. Funciona básicamente igual que git checkout <commit #> , pero no crea un estado de head desasociado.
  • --mixed: restablece el HEAD a la confirmación que selecciones en el historial y deshace los cambios en el índice.
  • --hard: restablece el HEAD a la confirmación que selecciones en el historial, deshace los cambios en el índice y deshace los cambios en tu directorio de trabajo. En este tutorial, no probaremos el "hard reset".

Para ver una descripción completa de cómo funciona git reset, consulta el artículo Herramientas de Git: reset desmitificado (en inglés) de git-scm.com.

 

A medida que avances por el tutorial, aprenderás varios comandos más de git como parte del aprendizaje de cómo deshacer cambios, así que pongámonos manos a la obra.

Bifurca un repositorio

Vamos a empezar creando un repositorio único con todo el código del original. Este proceso se llama "bifurcación de un repositorio". La bifurcación es un proceso de git ampliado que se activa cuando un repositorio compartido está alojado en un servicio de alojamiento de terceros como Bitbucket.

  1. Haz clic en la siguiente URL o escríbela: https://bitbucket.org/atlassian/tutorial-documentation-tests/commits/all
  2. Haz clic en el símbolo + de la barra lateral izquierda, selecciona Bifurcar este repositorio, revisa el cuadro de diálogo y haz clic en Bifurcar repositorio.
  3. Deberías acceder al resumen del nuevo repositorio.
  4. Haz clic en el símbolo + y selecciona Clonar este repositorio.
  5. En tu ordenador, clona el repositorio.
  6. Navega al directorio que contiene el repositorio clonado.

Ahora que tienes un repositorio lleno de código y un historial existente en tu sistema local, estás listo para empezar a deshacer algunos cambios.

Busca cambios en tu sistema local

Tendrás que ser capaz de buscar y consultar el cambio que quieres deshacer. Esto puede hacerse examinando la IU de confirmación en Bitbucket y hay unas cuantas utilidades de líneas de comandos que pueden localizar un cambio específico.

git status

Git status devuelve el estado de tu directorio de trabajo (la ubicación del repositorio en tu sistema local) y el entorno de ensayo (donde preparas un conjunto de cambios para añadirlos al historial del proyecto). Mostrará todos los archivos que tengan cambios y si dichos cambios se han añadido al entorno de ensayo. Ahora vamos a ejecutar git status y a examinar el estado actual del repositorio.

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

El resultado de git status aquí nos muestra que todo está actualizado con la rama maestra remota y que no hay cambios pendientes esperando a confirmarse. En el siguiente ejemplo, haremos algunos cambios en el repositorio y lo examinaremos en un estado de cambios pendientes. Esto significa que tienes cambios en los archivos del repositorio de tu sistema local que no has preparado para añadirlos al historial del proyecto.

Para reproducir el siguiente ejemplo,  primero abre el archivo myquote2.html. Haz algunas modificaciones en el contenido de myquote2.html, guarda y sal del archivo. Vamos a ejecutar una vez más git status para examinar el repositorio en este estado.

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
 
Changes not staged for commit:
 (use "git add <file>..." to update what will be committed)
 (use "git checkout -- <file>..." to discard changes in working directory)
 
 Modified: myquote2.html
 
no changes added to commit (use "git add" and/or "git commit -a")
--

Aquí el resultado muestra que el repositorio tiene modificaciones pendientes en myquote2.html. ¡Buenas noticias! Si, como en el ejemplo anterior, el cambio que quieres deshacer no se ha añadido al entorno de ensayo todavía, puedes simplemente editar el archivo y seguir trabajando. Git solo empieza a realizar el seguimiento de un cambio cuando lo añades al entorno de ensayo y, a continuación, lo confirmas en el historial del proyecto.

Ahora vamos a "deshacer" los cambios que hemos hecho en myquote2.html. Como esto es un ejemplo simplificado con cambios mínimos, tenemos dos métodos disponibles para deshacer los cambios.  Si ejecutamos git checkout myquote2.html, el repositorio restaurará myquote2.html a la versión confirmada anterior. Otra opción es ejecutar git reset --hard que revertirá todo el repositorio a la última confirmación.

git log

El comando git log te permite ver el historial del proyecto, filtrarlo y buscar cambios concretos. Mientras que git status te permite examinar el directorio de trabajo y el entorno de ensayo, git log solo muestra el historial confirmado.

El mismo registro de historial confirmado puede encontrarse en la IU de Bitbucket accediendo a la vista "confirmaciones" de un repositorio. La vista de confirmaciones de nuestro repositorio de demostración se puede encontrar en la siguiente dirección: https://bitbucket.org/dans9190/tutorial-documentation-tests/commits/all. Esta vista tendrá resultados similares a la utilidad de línea de comandos de git log. Puede utilizarse para buscar e identificar una confirmación para deshacerla.

En el siguiente ejemplo, puedes ver varias cosas en el historial, pero cada cambio es, fundamentalmente, una confirmación. Así que eso es lo que tendremos que buscar y deshacer.

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working tree clean

$ git log

commit 1f08a70e28d84d5034a8076db9103f22ec2e982c
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Wed Feb 7 17:06:50 2018 +0000

    Initial Bitbucket Pipelines configuration

commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Fri Sep 30 15:50:58 2016 -0700

    repeated quote to show how a change moves through the process

commit 4801b87c2147dce83f1bf31acfcffa6cb1d7e0a5
Merge: 1a6a403 3b29606
Author: Dan Stevens [Atlassian] <dstevens@atlassian.com>
Date:   Fri Jul 29 18:45:34 2016 +0000

    Merged in changes (pull request #6)

    Changes

Vamos a examinar más en detalle una de las confirmaciones de la lista:

commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Fri Sep 30 15:50:58 2016 -0700
 
    repeated quote to show how a change moves through the process

Lo que puedes ver es que cada mensaje de confirmación tiene cuatro elementos:

Elemento Descripción

Hash de la confirmación

Una cadena alfanumérica (con codificación SHA-1) que identifica este cambio específico

Autor

La persona que confirmó el cambio

Fecha

La fecha en la que el cambio se confirmó en el proyecto

Mensaje de confirmación

Una cadena de texto que describe los cambios.

Consejo práctico: escribe mensajes de confirmación cortos y descriptivos para ayudar a crear un repositorio de trabajo más armonioso para todo el mundo.


 

 

Localiza una confirmación específica

Lo más probable es que el cambio que quieres deshacer esté en algún punto anterior del historial del proyecto que puede ser bastante extenso. Así que vamos a aprender un par de operaciones básicas utilizando git log para buscar un cambio específico.

  1. Ve a la ventana de tu terminal y navega hasta el nivel superior de tu repositorio local utilizando el comando cd (cambiar directorio).
$ cd ~/repos/tutorial-documentation-tests/

Introduce el comando git log --oneline. Al añadir --oneline, se mostrará cada confirmación en una línea única, lo que te permite ver más historial en tu terminal.

Pulsa la tecla q para salir del registro de confirmaciones y volver a tu símbolo del sistema en cualquier momento.

Deberías ver algo como el siguiente ejemplo:

$ git log --oneline
1f08a70 (HEAD -> master, origin/master, origin/HEAD) Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
...
  1. Pulsa la tecla q para volver al símbolo del sistema.
  2. Localiza la confirmación con el hash c5826da y más cambios en la lista que el comando git log ha creado. Alguien no escribió un mensaje de confirmación descriptivo, por lo que tendremos que averiguar si tiene los cambios que necesitamos.
  3. Resalta y copia el hash de la confirmación c5826da del resultado del comando git log en la ventana de tu terminal.
  4. Escribe git show y, a continuación, pega o transcribe el hash de la confirmación que has copiado y pulsa Intro. Deberías ver algo como esto:
$git show c5826daeb6ee3fd89e63ce35fc9f3594fe243605
commit c5826daeb6ee3fd89e63ce35fc9f3594fe243605
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Tue Sep 8 13:50:23 2015 -0700

    more changes

diff --git a/README.md b/README.md
index bdaee88..6bb2629 100644
--- a/README.md
+++ b/README.md
@@ -11,12 +11,7 @@ This README would normally document whatever steps are necessary to get your app
 ### How do I get set up? ###

 * Summary of set up
-* Configuration
-* Dependencies
-* Database configuration
-* How to run tests
-* Deployment instructions
-* more stuff and things
:

El mensaje de la parte inferior seguirá rellenándose hasta que se muestre el cambio completo. Pulsa q para salir al símbolo del sistema.

Filtra el registro de git para buscar una confirmación específica

Puedes filtrar y ajustar el resultado del git log con las siguientes adiciones:

Este filtro Hace esto Este comando de ejemplo Tendría como resultado esto
-<n>

Limita el número de confirmaciones mostradas

git log -10

Las 10 confirmaciones más recientes en el historial

--after

--before

Limita las confirmaciones mostradas al periodo relacionado

Puedes usar también --after "aaaa-mm-dd" --before "aaaa-mm-dd"

git log --after 2017-07-04

Todas las confirmaciones después del 4 de julio de 2017

--author="nombre"

Enumera todas las confirmaciones cuyo autor coincida con el nombre

git log --author="Alana"

Todas las confirmaciones hechas por cualquier autor con Alana en el campo de nombre

--grep="cadena de mensaje"

Devuelve cualquier confirmación con un mensaje de confirmación que coincida con la cadena que has introducido

git log --grep="HOT-"

Todas las confirmaciones con HOT- como cadena de texto en sus mensajes

 

Ha sido una explicación muy por encima del comando git log. Si te gusta trabajar con este comando, puede que te interese consultar el tutorial avanzado de git log.

Deshaz un cambio con git reset

Para empezar, vamos a deshacer la última confirmación del historial. En este caso, vamos a suponer que acabas de activar los canales de soluciones de CI/CD de Bitbucket, pero te has dado cuenta de que el script no está bien del todo.

  1. Introduce git log --oneline en la ventana de tu terminal.
  2. Copia el hash de confirmación de la segunda confirmación en log: 52f823c y después pulsa q para salir del registro.
  3. Introduce git reset --soft 52f823c en la ventana de tu terminal. El comando debería ejecutarse en segundo plano si todo está bien.  Ya está, has deshecho tu primer cambio. Ahora vamos a ver el resultado de esta acción.
  4. Introduce git status en la ventana de tu terminal. Verás que se ha deshecho la confirmación y ahora es un cambio no confirmado. Debería ser algo así:
$ git status
On branch master
Your branch is behind 'origin/master' by 1 commit, 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:   bitbucket-pipelines.yml
  1. Introduce git log --oneline en la ventana de tu terminal. Deberías ver algo como esto:
$ git log --oneline
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
...
  1. Puedes ver que el nuevo HEAD de la rama es la confirmación 52f823c, que es exactamente lo que querías.
  2. Pulsa q para salir del registro. Deja el terminal abierto, porque, ahora que has aprendido cómo hacer un restablecimiento sencillo, vamos a probar algo un poco más complicado.

Deshaz varios cambios con git reset

Supongamos que te has dado cuenta de que la solicitud de incorporación de cambios n.º 6 (4801b87) tiene que modificarse y quieres mantener un historial limpio, por lo que restablecerás el HEAD para que confirme 1a6a403. Esta vez utilizarás el comando git reset.

  1. Introduce git log --online.
  2. Copia el hash de la confirmación 1a6a403 (myquote editado en línea con Bitbucket)  que es la confirmación justo debajo de la solicitud de incorporación de cambios n.º 6 que tiene los cambios que queremos deshacer.
  3. Introduce git reset 1a6a403 en la ventana de tu terminal. El resultado debería ser algo así:
$ git reset 1a6a403
Unstaged changes after reset:
M README.md
M myquote2.html

Puedes ver que los cambios ahora están en un estado sin confirmar. Eso significa que ahora hemos eliminado varios cambios tanto del historial del proyecto como del entorno de ensayo.

  1. Introduce git status en la ventana de tu terminal. El resultado debería ser algo así:

$ git status
On branch master
Your branch is behind 'origin/master' by 6 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)
 
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
    modified:   README.md
    modified:   myquote2.html
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
    bitbucket-pipelines.yml
 
no changes added to commit (use "git add" and/or "git commit -a")

Ahora puedes ver que el primer cambio que deshicimos (el archivo bitbucket-pipelines.yml) ya no cuenta con seguimiento por parte de git. Esto se debe a que invocar git reset elimina el cambio tanto del encabezado de la rama como del seguimiento o área de índice de git. El proceso subyacente es un poco más complejo de lo que podemos tratar aquí. Puedes leer más en git reset.

  1. Introduce git log --oneline en la ventana de tu terminal.
1a6a403 myquote edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'master' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
879f965 adding to the quote file
8994332 Merged in HOT-235 (pull request #2)
b4a0b43 removed sarcastic remarks because they violate policy.
b5f5199 myquote2.html created online with Bitbucket
b851618 adding my first file
5b43509 writing and using tests

El resultado del registro ahora muestra que el historial de confirmaciones también se ha modificado y empieza en la confirmación 1a6a403. Para demostrarlo y tener más ejemplos, supongamos que ahora queremos deshacer el restablecimiento que acabamos de hacer. Tras pensarlo mejor, quizás queríamos conservar el contenido de la solicitud de incorporación de cambios n.º 6.  

Envío de restablecimientos a Bitbucket

Git reset es uno de los métodos de "deshacer" que ofrece git. Generalmente, los restablecimientos se consideran una opción "insegura" para deshacer cambios. Los restablecimientos están bien cuando se trabaja localmente con código aislado, pero son arriesgados cuando se comparten con miembros del equipo.

Para compartir una rama que se ha restablecido con un equipo remoto, se tiene que ejecutar un "envío forzado". Un "envío forzado" se inicia ejecutando git push -f. Un envío forzado destruirá cualquier historial en la rama que se haya creado tras el punto del envío.

Un ejemplo de este escenario "inseguro" es el siguiente:

  • El desarrollador A ha estado trabajando en una rama desarrollando una nueva función.
  • El desarrollador B ha estado trabajando en la misma rama desarrollando otra función.
  • El desarrollador B decide restablecer la rama a un estado anterior antes de que tanto el desarrollador A como el B empezaran a trabajar.
  • Entonces el desarrollador B envía de forma forzosa la rama restablecida al repositorio remoto.
  • El desarrollador A incorpora los cambios de la rama para recibir las actualizaciones. Durante esta incorporación de cambios, el desarrollador A recibe la actualización forzada. Esto restablece la rama local del desarrollador A a un punto anterior a que empezase a trabajar en su función y pierde sus confirmaciones.

Deshaz un git reset

Hasta ahora hemos estado utilizando hashes sha de git commit para ejecutar el comando git reset. Al resultado de git log ahora le faltan confirmaciones que hemos restablecido. ¿Cómo recuperaremos esas confirmaciones? Git nunca elimina por completo una confirmación a menos que se hayan desasociado los punteros. Asimismo, git almacena un registro independiente de todo el movimiento de referencia que se llama "registro de referencia". Podemos examinar el registro de referencia ejecutando git reflog.

1a6a403 HEAD@{0}: reset: moving to 1a6a403
1f08a70 HEAD@{1}: reset: moving to origin/master
1f08a70 HEAD@{2}: clone: from git@bitbucket.org:dans9190/tutorial-documentation-tests.git

Tu resultado del git reflog debería ser parecido al de arriba. Puedes ver un historial de las acciones del repositorio. La línea superior es una referencia al restablecimiento que hicimos para restablecer la solicitud de incorporación de cambios n.º 6. Ahora vamos a restablecer el restablecimiento para restaurar la solicitud de incorporación de cambios n.º 6. La segunda columna de este resultado del registro de referencia indica un puntero de referencia a una acción de modificación que se realiza en el repositorio. Aquí HEAD@{0} es una referencia al comando de restablecimiento que hemos ejecutado anteriormente. No queremos responder a ese comando de restablecimiento, así que restableceremos el repositorio a HEAD@{1}.

$ git reset --hard HEAD@{1}
HEAD is now at 1f08a70 Initial Bitbucket Pipelines configuration

Ahora vamos a examinar el historial de confirmaciones del repositorio con git log --oneline:

$git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'master' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:

Aquí podemos ver que el historial de confirmaciones del repositorio se ha restaurado a la versión anterior con la que estábamos haciendo pruebas. Podemos ver que la confirmación 4801b87 se ha restaurado aunque aparecía perdida en la primera operación de restablecimiento. El comando git reflog es una herramienta potente para deshacer cambios en el repositorio. Puedes encontrar información más detallada sobre su uso en la página de git reflog.

git revert

En los ejemplos anteriores, hemos realizado operaciones de deshacer viajando atrás en el tiempo mediante los comandos git reset y git reflog. Git contiene otra utilidad de "deshacer" que suele considerarse "más segura" que el restablecimiento. La reversión crea nuevas confirmaciones que contienen lo contrario de los cambios en las confirmaciones especificados. En ese momento, estas confirmaciones revertidas pueden enviarse de forma segura a los repositorios remotos para compartirlas con otros desarrolladores.

En la siguiente sección, demostraremos el uso de git revert. Vamos a continuar con nuestro ejemplo de la sección anterior. Para empezar, vamos a examinar el registro y buscaremos una confirmación para revertirla.

$ git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'master' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:

Para este ejemplo, vamos a coger la confirmación más reciente 1f08a70 como nuestra confirmación con la que vamos a trabajar. Para este escenario, supongamos que queremos deshacer las ediciones que hemos hecho en esa confirmación. Ejecuta:

$ git revert 1f08a70

Así se iniciará un flujo de trabajo de git merge. Git creará una nueva confirmación cuyo contenido es lo contrario de la confirmación que se especificó para la reversión. Entonces Git abrirá un editor de texto configurado para solicitar un nuevo mensaje de confirmación. Las reversiones se consideran la opción de deshacer más segura a causa de este flujo de trabajo de confirmación. La creación de confirmaciones revertidas deja un rastro claro en el historial de confirmaciones del momento en el que se ejecutó una operación de deshacer.

¡Ya has aprendido a deshacer cambios!

¡Enhorabuena, has terminado! Vuelve a este tutorial en cualquier momento o ve a la sección Deshacer cambios para obtener información más detallada. Sigue trabajando así de bien en Bitbucket.