Al Sweigart
Digamos que tengo un repositorio git con un archivo modificado llamado Léame.txt, y quiero deshacer las modificaciones que hice y volver a establecer el estado de la confirmación más reciente. Parece que hay dos comandos para hacer esto:
git checkout -- readme.txt
y
git restore readme.txt
¿Hay alguna diferencia entre estos dos comandos? me he dado cuenta de que git status
ofrece el consejo “(use "git restore <file>..." to discard changes in working directory)
“. ¿Es esta la forma canónica de deshacer modificaciones no confirmadas? ¿Son ambas formas igualmente válidas y populares?
axiac
git restore
es un comando introducido en Git 2.23 (agosto de 2019) junto con git switch
. Sus propósitos son simplificar y separar los casos de uso de git checkout
que hace demasiadas cosas.
git checkout
se puede usar para cambiar de rama (y también para crear una nueva rama antes de cambiar a ella). Esta funcionalidad ha sido extraída en git switch
.
git checkout
también se puede usar para restaurar archivos al estado en el que se encontraban en una confirmación específica. Esta funcionalidad ha sido extraída en git restore
.
Todavía pueden ser realizados por git checkout
pero los nuevos comandos son más fáciles de usar y menos confusos.
Para resumir,
git restore readme.txt
es una nueva forma de hacer lo que solías hacer con:
git checkout -- readme.txt
Lea también la respuesta de torek. Analiza la seguridad de git checkout
operaciones de y proporciona un ejemplo cuando git checkout
produce resultados inesperados en versiones anteriores de Git.
Me gustan las dos respuestas sobre esto en el momento en que escribo la mía, tanto la respuesta de axiac como la de kapsiR, pero la forma en que lo expresaría es esta:
-
git checkout
combina demasiados comandos en una interfaz. Algunos de estos comandos son “seguros”, ya que si tiene trabajo no comprometido, no destruirlo, y algunos de estos son “inseguros”, en el sentido de que si tiene trabajo no comprometido y dígales destruir mi trabajo no comprometidoellos harán eso. -
git switch
implementa el subconjunto “seguro”. -
git restore
implementa el subconjunto “inseguro”.
Hasta ahora, no hay ninguna razón en particular para preferir el antiguo comando único o el nuevo par de comandos. Pero añadimos un elemento más:
git checkout name
puede ejecutar cualquiera el inseguro uno o el seguro uno, ¡dependiendo de algo en lo que quizás ni siquiera estés pensando!
Ahora, este último punto está corregido en las últimas versiones de Git. Supongamos que tiene un seguimiento remoto origin/dev
nombre y te gustaría crear una rama dev
respectivamente. Normalmente, podría simplemente ejecutar:
git checkout dev
Sin embargo, suponga que su actual (probablemente master
) la caja tiene un directorio llamado dev
, y en ese directorio, ha realizado un montón de trabajo y aún no lo ha confirmado. Acabas de recordar: Debería comprometer todo este trabajo que acabo de hacer en el dev
rama, no la master
rama.
Ahora, no existe dev
rama en absoluto, pero hay son dev/
archivos. Esto es lo que hace un viejo Git:
sh-3.2$ git --version
git version 2.20.1
sh-3.2$ git branch -r
origin/dev
(eso es, origin/dev
existe; rama dev
no lo hace y estoy en master
aquí)
sh-3.2$ git status --short
M dev/file
sh-3.2$ git diff
diff --git a/dev/file b/dev/file
index e69de29..c238a0b 100644
--- a/dev/file
+++ b/dev/file
@@ -0,0 +1 @@
+look at all this work I did
Agregar esa línea tomó semanas de trabajo duro! 🙂
sh-3.2$ git checkout dev
UH oh. ¿Por qué no me dijo acerca de la creación de una rama llamada dev
configurado para rastrear origin/dev
?
sh-3.2$ git status
On branch master
nothing to commit, working tree clean
¡Gah! ¡Mi trabajo duro se ha ido!
El problema aquí es que git checkout
corrió el inseguro dominio. Podría haber esperado que usara el seguro… pero no lo hizo.
Un Git más moderno (2.24.0) me dirá que git checkout dev
es ambiguo, lo cual es bueno: no solo destruye mi archivo. (No he probado Git 2.23 en sí, donde entraron por primera vez los comandos de división en dos).
De todos modos, usando el nuevo comandos, al menos sabe, justo cuando escribe el comando, si obtendrá el modo seguro o el inseguro. Si tus hábitos están establecidos y sigues usando git checkout
o le preocupa la nota que dice que estos nuevos comandos aún son experimentales, aún puede usar el anterior, y ya no solo elimina el trabajo, en el caso ambiguo.
KapsiR
Como se indica en los documentos:
o puede restaurar tanto el índice como el árbol de trabajo (es lo mismo que usar git-checkout1)
Es una manera conveniente de hacer lo mismo. (primera versión en Git 2.23)
Publicación de blog de GitHub sobre aspectos destacados de Git 2.23:
Git 2.23 trae un nuevo par de comandos experimentales al conjunto de comandos existentes:
git switch
ygit restore
. Estos dos están destinados a proporcionar eventualmente una mejor interfaz para el conocidogit checkout
. Los nuevos mandos pretenden que cada uno tenga una separación clara, repartiendo ordenadamente cuáles son las muchas responsabilidades degit checkout
como mostraremos a continuación.