¿Cuál es la diferencia entre "git reset" y "git checkout"?
Siempre he pensado en git reset
y git checkout
como lo mismo, en el sentido de que ambos devuelven el proyecto a un compromiso específico. Sin embargo, creo que no pueden ser exactamente iguales, ya que sería redundante. ¿Cuál es la diferencia real entre los dos? Estoy un poco confundido, ya que svn solo tiene svn co
que revertir la confirmación.
AGREGADO
VonC y Charles explicaron muy bien las diferencias entre git reset
y . git checkout
Mi comprensión actual es que git reset
revierte todos los cambios a una confirmación específica, mientras que git checkout
más o menos se prepara para una rama. Los siguientes dos diagramas me parecieron bastante útiles para llegar a este entendimiento:
AGREGADO 3
Desde http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html , el pago y el restablecimiento pueden emular la rebase.
git checkout bar
git reset --hard newbar
git branch -d newbar
git reset
Se trata específicamente de actualizar el índice , mover el HEAD.git checkout
se trata de actualizar el árbol de trabajo (al índice o al árbol especificado). Actualizará el HEAD solo si realiza el pago en una sucursal (de lo contrario, terminará con un HEAD separado ).
(En realidad, con Git 2.23 Q3 2019, esto serágit restore
, no necesariamentegit checkout
)
En comparación, dado que svn no tiene índice, solo un árbol de trabajo, svn checkout
copiará una revisión determinada en un directorio separado.
El equivalente más cercano para git checkout
sería:
svn update
(si estás en la misma rama, es decir, la misma URL SVN)svn switch
(si realiza el pago, por ejemplo, en la misma sucursal, pero desde otra URL del repositorio SVN)
Todas esas tres modificaciones del árbol de trabajo ( ,, svn checkout
) tienen un solo comando en git :.
Pero como git también tiene la noción de índice (esa "área de preparación" entre el repositorio y el árbol de trabajo), también tienes .update
switch
git checkout
git reset
Thinkeye menciona en los comentarios el artículo " Reset Demystified ".
Por ejemplo, si tenemos dos ramas, '
master
' y 'develop
' que apuntan a confirmaciones diferentes, y actualmente estamos en 'develop
' (por lo que HEAD apunta a ella) y ejecutamosgit reset master
, 'develop
' ahora apuntará a la misma confirmación que 'master
' hace.Por otro lado, si en lugar de eso ejecutamos
git checkout master
, 'develop
' no se moverá,HEAD
él mismo lo hará.HEAD
ahora apuntará a 'master
'.Entonces, en ambos casos vamos a apuntar
HEAD
a confirmarA
, pero la forma de hacerlo es muy diferente.reset
moverá losHEAD
puntos de la rama, el pagoHEAD
se mueve para apuntar a otra rama.
Sin embargo, sobre esos puntos:
LarsH agrega en los comentarios :
Sin embargo, el primer párrafo de esta respuesta es engañoso: "
git checkout
... actualizará el HEAD sólo si paga una rama (si no, terminará con un HEAD separado)".
No es cierto:git checkout
actualizará el HEAD incluso si verifica una confirmación que no es una rama (y sí, termina con un HEAD separado, pero aún así se actualizó).git checkout a839e8f updates HEAD to point to commit a839e8f.
De Novo coincide en los comentarios :
@LarsH tiene razón.
La segunda viñeta tiene una idea errónea sobre en qué se encuentra HEAD y actualizará HEAD solo si compra una sucursal.
HEAD va donde quiera que estés, como una sombra.
Al extraer alguna referencia que no sea una rama (por ejemplo, una etiqueta), o una confirmación directamente, se moverá HEAD. La cabeza separada no significa que se haya separado de la CABEZA, significa que la cabeza está separada de una rama ref, desde la cual puede ver, por ejemplo,git log --pretty=format:"%d" -1
.
- Los estados principales adjuntos comenzarán con
(HEAD ->
,- detached seguirá mostrándose
(HEAD
, pero no tendrá una flecha hacia una referencia de rama.
En su forma más simple, reset
restablece el índice sin tocar el árbol de trabajo, mientras checkout
cambia el árbol de trabajo sin tocar el índice.
Restablece el índice para que coincida HEAD
, el árbol de trabajo se deja solo:
git reset
Conceptualmente, esto verifica el índice en el árbol de trabajo. Para que realmente haga algo, tendría que usar -f
para forzarlo a sobrescribir cualquier cambio local. Esta es una característica de seguridad para garantizar que el formulario "sin argumentos" no sea destructivo:
git checkout
Una vez que comienzas a agregar parámetros, es cierto que hay cierta superposición.
checkout
Generalmente se usa con una rama, etiqueta o confirmación. En este caso, se restablecerá HEAD
el índice de la confirmación dada y también se realizará la extracción del índice en el árbol de trabajo.
Además, si lo proporciona, --hard
puede reset
solicitar reset
sobrescribir el árbol de trabajo y restablecer el índice.
Si actualmente tiene una sucursal registrada, existe una diferencia crucial entre reset
y checkout
cuándo proporciona una sucursal alternativa o se compromete. reset
cambiará la rama actual para que apunte a la confirmación seleccionada, mientras que checkout
dejará la rama actual sola pero verificará la rama proporcionada o confirmará en su lugar.
Otras formas de reset
e commit
implican el suministro de caminos.
Si proporciona rutas, reset
no podrá proporcionarlas --hard
y reset
solo cambiará la versión de índice de las rutas proporcionadas a la versión en la confirmación proporcionada (o HEAD
si no especifica una confirmación).
Si proporciona rutas a checkout
, reset
actualizará la versión de índice de las rutas proporcionadas para que coincida con la confirmación proporcionada (o HEAD
), pero siempre verificará la versión de índice de las rutas proporcionadas en el árbol de trabajo.
Un caso de uso simple al revertir un cambio:
1. Utilice restablecer si desea deshacer la preparación de un archivo modificado.
2. Utilice la opción de pago si desea descartar cambios en archivos no preparados.
La diferencia clave en pocas palabras es que reset
mueve la referencia de rama actual , mientras que checkout
no lo hace (mueve HEAD).
Como explica el libro Pro Git en Reset Demystified ,
Lo primero que
reset
haremos será mover aquello a lo que apunta HEAD . Esto no es lo mismo que cambiar el propio HEAD (que es lo quecheckout
hace);reset
mueve la rama a la que apunta HEAD. Esto significa que si HEAD está configurado en lamaster
rama (es decir, actualmente estás en lamaster
rama), la ejecucióngit reset 9e5e6a4
comenzarámaster
señalando9e5e6a4
. [énfasis añadido]
Consulte también la respuesta de VonC para obtener un texto muy útil y un extracto de diagrama del mismo artículo, que no duplicaré aquí.
Por supuesto, hay muchos más detalles sobre los efectos checkout
que reset
puede tener en el índice y el árbol de trabajo, dependiendo de los parámetros que se utilicen. Puede haber muchas similitudes y diferencias entre los dos comandos. Pero a mi modo de ver, la diferencia más crucial es si mueven la punta de la rama actual.