Git Reset vs Revert vs Rebase
Publicado: 2021-05-20En este artículo, aprenderá diferentes formas de jugar con las confirmaciones en Git.
Como desarrollador, se habría enfrentado a situaciones de este tipo varias veces en las que hubiera querido volver a una de sus confirmaciones anteriores, pero no estaba seguro de cómo hacerlo. E incluso si conoce los comandos de Git como restablecer, revertir, rebase, no es consciente de las diferencias entre ellos. Así que comencemos y entendamos qué son git reset, revert y rebase.
Restablecer Git
Git reset es un comando complejo y se usa para deshacer los cambios.
Puedes pensar en git reset como una función de reversión. Con git reset, puedes saltar entre varias confirmaciones. Hay tres modos de ejecutar un comando git reset: –soft, –mixed y –hard. De forma predeterminada, el comando git reset usa el modo mixto. En un flujo de trabajo de reinicio de git, tres mecanismos de administración internos de git entran en escena: HEAD , área de prueba (índice) y el directorio de trabajo .

El directorio de trabajo es el lugar donde está trabajando actualmente, es el lugar donde están presentes sus archivos. Usando un comando de estado de git, puede ver qué archivos / carpetas están presentes en el directorio de trabajo.
El área de ensayo (índice) es donde git rastrea y guarda todos los cambios en los archivos. Los cambios guardados se reflejan en el directorio .git. Utiliza git add "nombre de archivo" para agregar el archivo al área de preparación. Y como antes, cuando ejecute git status, verá qué archivos están presentes en el área de prueba.
La rama actual en Git se conoce como HEAD. Apunta a la última confirmación, que ocurrió en la rama de pago actual. Se trata como un puntero para cualquier referencia. Una vez que realiza el pago a otra sucursal, el HEAD también se mueve a la nueva sucursal.
Permítanme explicar cómo funciona git reset en los modos duro, suave y mixto. El modo difícil se usa para ir a la confirmación puntual, el directorio de trabajo se llena con archivos de esa confirmación y el área de preparación se restablece. En el restablecimiento parcial, solo se cambia el puntero a la confirmación especificada. Los archivos de todas las confirmaciones permanecen en el directorio de trabajo y el área de preparación antes del reinicio. En el modo mixto (predeterminado), el puntero y el área de preparación se restablecen.
Git Restablecer duro
El propósito de git hard reset es mover HEAD a la confirmación especificada. Eliminará todas las confirmaciones que ocurrieron después de la confirmación especificada. Este comando cambiará el historial de confirmaciones y apuntará a la confirmación especificada.
En este ejemplo, agregaré tres archivos nuevos, los confirmaré y luego realizaré un restablecimiento completo.
Como puede ver en el comando a continuación, en este momento, no hay nada que confirmar.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) nothing to commit, working tree cleanAhora, crearé 3 archivos y agregaré algo de contenido.
$ vi file1.txt $ vi file2.txt $ vi file3.txtAgregue estos archivos al repositorio existente.
$ git add file*Cuando vuelva a ejecutar el comando de estado, reflejará los nuevos archivos que acabo de crear.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: file1.txt new file: file2.txt new file: file3.txtAntes de comprometerme, déjame mostrarte, actualmente tengo un registro de 3 confirmaciones en Git.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testAhora, me comprometeré con el repositorio.
$ git commit -m 'added 3 files' [master d69950b] added 3 files 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txtSi utilizo ls-files, verá que se han agregado los nuevos archivos.
$ git ls-files demo dummyfile newfile file1.txt file2.txt file3.txtCuando ejecuto el comando log en git, tengo 4 confirmaciones y HEAD apunta a la última confirmación.
$ git log --oneline d69950b (HEAD -> master) added 3 files 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testSi voy y elimino el file1.txt manualmente y hago un estado de git, mostrará el mensaje de que los cambios no están preparados para su confirmación.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: file1.txt no changes added to commit (use "git add" and/or "git commit -a")Ahora, ejecutaré el comando de restablecimiento completo.
$ git reset --hard HEAD is now at d69950b added 3 filesSi vuelvo a comprobar el estado, descubriré que no hay nada que confirmar y el archivo que eliminé ha vuelto al repositorio. La reversión ocurrió porque después de eliminar el archivo, no me comprometí, por lo que después de un restablecimiento completo, volvió al estado anterior.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) nothing to commit, working tree cleanSi reviso el registro de git, así es como se verá.
$ git log commit d69950b7ea406a97499e07f9b28082db9db0b387 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 19:53:31 2020 +0530 added 3 files commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 testEl propósito del restablecimiento completo es apuntar a la confirmación especificada y actualizar el directorio de trabajo y el área de prueba. Déjame mostrarte un ejemplo más. Actualmente, la visualización de mis confirmaciones se ve a continuación:

Aquí, ejecutaré el comando con HEAD ^, lo que significa que quiero restablecer la confirmación anterior (una confirmación posterior).
$ git reset --hard HEAD^ HEAD is now at 0db602e one more commitPuede ver que el puntero principal ahora ha cambiado a 0db602e desde d69950b.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test 
Si comprueba el registro, la confirmación de d69950b desaparecerá y el encabezado ahora apunta a 0db602e SHA.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 TestSi ejecuta ls-files, puede ver que file1.txt, file2.txt y files3.txt ya no están en el repositorio porque esa confirmación y su archivo se eliminaron después del restablecimiento completo.
$ git ls-files demo dummyfile newfileReinicio suave de Git
Del mismo modo, ahora les mostraré un ejemplo de un reinicio por software. Considere, he agregado los 3 archivos nuevamente como se mencionó anteriormente y los comprometí. El registro de git aparecerá como se muestra a continuación. Puede ver que 'reinicio suave' es mi última confirmación, y HEAD también apunta a eso.
$ git log --oneline aa40085 (HEAD -> master) soft reset 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testLos detalles de la confirmación en el registro se pueden ver usando el siguiente comando.
$ git log commit aa400858aab3927e79116941c715749780a59fc9 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 21:01:36 2020 +0530 soft reset commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 testAhora, usando el reinicio por software, quiero cambiar a una de las confirmaciones más antiguas con SHA 0db602e085a4d59cfa9393abac41ff5fd7afcb14
Para hacer eso, ejecutaré el siguiente comando. Debe pasar más de 6 caracteres iniciales de SHA, no se requiere el SHA completo.

$ git reset --soft 0db602e085a4Ahora, cuando ejecuto el registro de git, puedo ver que HEAD se ha restablecido a la confirmación que especifiqué.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 testPero la diferencia aquí es que los archivos de la confirmación (aa400858aab3927e79116941c715749780a59fc9) donde había agregado 3 archivos todavía están en mi directorio de trabajo. No se han eliminado. Es por eso que debe usar un restablecimiento parcial en lugar de un restablecimiento completo. No hay riesgo de perder los archivos en el modo suave.
$ git ls-files demo dummyfile file1.txt file2.txt file3.txt newfileGit Revert
En Git, el comando revert se usa para realizar una operación de reversión, es decir, para revertir algunos cambios. Es similar al comando de reinicio, pero la única diferencia aquí es que realiza una nueva confirmación para volver a una confirmación en particular. En resumen, es justo decir que el comando git revert es una confirmación.
El comando de reversión de Git no elimina ningún dato mientras se realiza la operación de reversión.
Digamos que estoy agregando 3 archivos y realizando una operación de confirmación de git para el ejemplo de reversión.
$ git commit -m 'add 3 files again' [master 812335d] add 3 files again 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txtEl registro mostrará la nueva confirmación.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testAhora me gustaría volver a una de mis confirmaciones anteriores, digamos: "59c86c9 nueva confirmación". Ejecutaría el comando a continuación.
$ git revert 59c86c9Esto abrirá un archivo, encontrará los detalles de la confirmación a la que está tratando de revertir, y puede darle un nombre a su nueva confirmación aquí, y luego guardar y cerrar el archivo.
Revert "new commit" This reverts commit 59c86c96a82589bad5ecba7668ad38aa684ab323. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # Your branch is ahead of 'origin/master' by 4 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: dummyfileDespués de guardar y cerrar el archivo, esta es la salida que obtendrá.
$ git revert 59c86c9 [master af72b7a] Revert "new commit" 1 file changed, 1 insertion(+), 1 deletion(-)Ahora, para realizar los cambios necesarios, a diferencia del reinicio, revert ha realizado una nueva confirmación más. Si vuelve a comprobar el registro, encontrará una nueva confirmación debido a la operación de reversión.
$ git log --oneline af72b7a (HEAD -> master) Revert "new commit" 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test 
Git log tendrá todo el historial de confirmaciones. Si desea eliminar las confirmaciones del historial, revertir no es una buena opción, pero si desea mantener los cambios de confirmación en el historial, revertir es el comando adecuado en lugar de restablecer.
Git Rebase
En Git, rebase es la forma de mover o combinar confirmaciones de una rama sobre otra rama. Como desarrollador, no crearía mis funciones en la rama maestra en un escenario del mundo real. Trabajaría en mi propia rama (una 'rama de características'), y cuando tenga algunas confirmaciones en mi rama de características con la característica agregada, me gustaría moverla a la rama maestra.
Rebase a veces puede ser un poco confuso de entender porque es muy similar a una fusión. El objetivo de fusionar y reajustar ambos es tomar las confirmaciones de mi rama de características y colocarlas en una rama maestra o en cualquier otra rama. Considere, tengo un gráfico que se ve así:

Suponga que está trabajando en equipo con otros desarrolladores. En ese caso, puede imaginar que esto podría volverse realmente complejo cuando hay un montón de otros desarrolladores trabajando en diferentes ramas de funciones y han estado fusionando múltiples cambios. Se vuelve confuso rastrear.
Entonces, aquí es donde rebase ayudará. Esta vez, en lugar de hacer una fusión de git, haré una rebase, donde quiero tomar mis dos confirmaciones de ramas de características y moverlas a la rama maestra. Una rebase tomará todas mis confirmaciones de la rama de funciones y las moverá a la parte superior de las confirmaciones de la rama maestra. Entonces, detrás de escena, git está duplicando las confirmaciones de la rama de características en la rama maestra.

Este enfoque le dará un gráfico de línea recta limpio con todas las confirmaciones en una fila.

Hace que sea fácil rastrear qué confirmaciones fueron a dónde. Puedes imaginar que si estás en un equipo con muchos desarrolladores, todas las confirmaciones siguen seguidas. Por lo tanto, es muy fácil de seguir incluso si tiene muchas personas trabajando en el mismo proyecto al mismo tiempo.
Déjame mostrarte esto de manera práctica.
Así es como se ve mi rama maestra actualmente. Tiene 4 confirmaciones.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testEjecutaré el siguiente comando para crear y cambiar a una nueva rama llamada característica, y esta rama se creará a partir de la segunda confirmación, es decir, 59c86c9
(master) $ git checkout -b feature 59c86c9 Switched to a new branch 'feature'Si verifica el registro en la rama de funciones, solo tiene 2 confirmaciones provenientes del maestro (línea principal).
(feature) $ git log --oneline 59c86c9 (HEAD -> feature) new commit e2f44fc (origin/master, origin/HEAD) testCrearé la característica 1 y la enviaré a la rama de características.
(feature) $ vi feature1.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 1' [feature c639e1b] feature 1 1 file changed, 1 insertion(+) create mode 100644 feature1.txtCrearé una característica más, es decir, la característica 2, en la rama de características y la confirmaré.
(feature) $ vi feature2.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 2' [feature 0f4db49] feature 2 1 file changed, 1 insertion(+) create mode 100644 feature2.txtAhora, si revisa el registro de la rama de funciones, tiene dos nuevas confirmaciones, que ejecuté anteriormente.
(feature) $ git log --oneline 0f4db49 (HEAD -> feature) feature 2 c639e1b feature 1 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testAhora quiero agregar estas dos nuevas características a la rama maestra. Para eso, usaré el comando rebase. Desde la rama de funciones, me basaré en la rama maestra. Lo que esto hará es volver a anclar mi rama de características contra los últimos cambios.
(feature) $ git rebase master Successfully rebased and updated refs/heads/feature.Ahora voy a seguir adelante y verificar la rama maestra.
(feature) $ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits)Y finalmente, vuelva a basar la rama maestra con mi rama de características. Esto tomará esas dos nuevas confirmaciones en mi rama de características y las reproducirá en la parte superior de mi rama maestra.
(master) $ git rebase feature Successfully rebased and updated refs/heads/master.Ahora, si verifico el registro en la rama maestra, puedo ver que las dos confirmaciones de mi rama de características se han agregado a mi rama maestra con éxito.
(master) $ git log --oneline 766c996 (HEAD -> master, feature) feature 2 c036a11 feature 1 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testSe trataba de reiniciar, revertir y reajustar los comandos en Git.
Conclusión
Se trataba de reiniciar, revertir y reajustar los comandos en Git. Espero que esta guía paso a paso te haya resultado útil. Ahora, ya sabe cómo jugar con sus confirmaciones según la necesidad utilizando los comandos mencionados en el artículo.
