“git checkout”和“git restore”在撤销未提交的文件更改方面有什么区别?

21

假设我有一个带有修改后文件readme.txt的git仓库,我想撤销我所做的修改并将其设置为最近提交状态。看起来有两个命令可以做到这一点:

git checkout -- readme.txt

git restore readme.txt

这两条命令有什么区别吗?我注意到 git status 给出了建议 "(use "git restore <file>..." to discard changes in working directory)"。这是撤消未提交修改的规范方式吗?两种方法都同样有效和流行吗?

3个回答

38

git restore 是 Git 2.23(2019年8月)与git switch一同引入的命令。它们的目的是简化和分离git checkout的用例,因为该命令执行了太多的操作。

git checkout 可以用于切换分支(并在切换到新分支之前创建新分支)。这个功能已经被提取到git switch中。

git checkout 还可以用于将文件恢复到指定提交时的状态。这个功能已经被提取到git restore中。

它们仍然可以通过git checkout执行,但新命令更易于使用,更不容易混淆。

总之,

git restore readme.txt

是一种新的方式来完成以前使用以下方法完成的任务:

git checkout -- readme.txt

还要阅读{{link1:Torek的答案}}。它分析了git checkout操作的安全性,并提供了一个示例,说明在旧版本的Git中git checkout会产生意外结果。


8

我喜欢在我写这篇文章时看到的两个答案——axiac的答案kapsiR的答案,但我会这样表述:

  • git checkout 结合了太多命令作为一个前端。其中一些命令是“安全”的,因为如果您有未提交的工作,它们则不会破坏它,而另一些命令是“不安全”的,因为如果您有未提交的工作并告诉它们破坏我的未提交的工作,它们会这样做。

  • git switch 实现了“安全”子集。

  • git restore 实现了“不安全”子集。

到目前为止,没有特别的理由支持旧的单一命令或新的两个命令。但我们再添加一项:

  • git checkout 名称 可能会执行不安全的安全的之一,这取决于你可能甚至没有考虑过的某些东西!

现在,在最新的Git版本中,这个问题已经得到解决。假设您有一个远程跟踪 origin/dev 名称,并希望相应地创建分支 dev。通常,您只需要运行:

git checkout dev

假设你当前(可能是master)的检出中有一个名为dev目录,并且在该目录中,你做了一堆工作,但尚未提交。现在你突然想起:我应该将所有这些工作提交到dev分支上,而不是master分支。 现在,根本没有现有的dev分支,但是有dev/文件。下面是旧版Git的操作:
sh-3.2$ git --version
git version 2.20.1
sh-3.2$ git branch -r
  origin/dev

(也就是说,origin/dev 存在;分支 dev 不存在,而我在这里是在主分支 master 上)
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

加入那行代码花费了好几周的辛苦工作! :-)

sh-3.2$ git checkout dev

哎呀,为什么它没有告诉我如何创建一个名为 dev 的分支并跟踪 origin/dev 呢?

sh-3.2$ git status
On branch master
nothing to commit, working tree clean

啊!我的辛勤努力全没了!

问题在于git checkout使用了不安全的命令。我可能本来期望它使用安全模式,但它没有。

更现代的Git(2.24.0)会告诉我git checkout dev是有歧义的,这很好:它不会简单地覆盖我的文件。(我还没有测试过首次拆分成两个命令的Git 2.23。)

无论如何,使用新的命令,你至少知道,在输入命令时,你将获得安全模式还是不安全的模式。如果你已经养成习惯并继续使用git checkout,或者你担心这些新命令仍处于实验阶段的提示,你仍然可以使用旧命令——在有歧义的情况下,它不再简单地清除工作内容。


4

正如文档中所述

或者你可以恢复索引和工作树(这相当于使用 git-checkout1)。

这是完成同样任务的便捷方式。(Git 2.23 中的第一个版本)

GitHub 的博客文章 关于 Git 2.23 的亮点:

Git 2.23 带来了一对新的实验性命令,加入到现有的命令套件中:git switchgit restore这两个命令旨在最终提供更好的接口,以取代众所周知的 git checkout 新命令打算分别具有明确的分离,将 git checkout 的许多职责整齐地分成不同部分,如下所示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接