为什么git checkout不会删除新文件?

7
假设我创建了一个文件file.txt(但并未提交),然后输入git checkout HEADgit checkout HEAD .。 我以为git checkout基本上会用给定的提交中的快照替换你当前工作目录中的文件,所以我认为这将删除file.txt。 但它并没有删除。为什么?

1
好的,因为你的假设是错误的。git checkout 不会影响未跟踪的文件。 - Sergio Tulentsev
1
Git 只管理已跟踪的文件,并且它非常努力地避免让您丢失数据(这是至关重要的)。 - coreyward
@SergioTulentsev,我认为这并不是一个很好的表述方式。 “Untracked”只是意味着“目前未在暂存区中”。即使您没有将这些更改放入暂存区,git checkout 仍会修改与上次提交时不同的文件。 - Jack M
@JackM 不,这不是 Git 中“未跟踪”的意思。 - Sergio Tulentsev
1
Git书并没有真正反对:索引通常是通过git checkout填充的,所以现在索引中的内容是快照中的内容。但是,如果您更改索引(例如使用git rm --cachedgit add),则会更改跟踪文件的集合。还要注意,git checkout <tree-ish> <paths>命令与git checkout <branch>命令非常不同。一些人(包括我自己)认为它应该使用不同的拼写,即根本不以git checkout开头。 - torek
显示剩余6条评论
2个回答

7

git checkout的设计不会覆盖您的工作副本。

它与git reset --hard以相同的方式工作,但有一个重要的区别 - git checkout是“工作目录安全”的,因此它不会覆盖工作目录中的现有更改。 实际上,它比较聪明——它在工作目录中尝试进行简单的合并。

因此,如果您想放弃所有更改,只使用HEAD快照,请使用git reset --hard HEAD或者只使用git reset --hard

但是,即使是git reset --hard也不会删除您的未跟踪文件。 要删除未跟踪的文件:

  • 运行git clean --dry-run。 它只是告诉���将要删除什么。 这样做是因为清理是一条危险的命令。
  • 运行git clean --force以最终删除未跟踪的文件。

您可以在这里找到有关git checkoutgit reset的更多详细信息,以及这里有关清理的更多详细信息。


1

file.txt是未被跟踪的,对于Git而言,它是“不可见”的。如果在你检出的提交中有另一个名为file.txt的文件,则它可能会因检出的“副作用”而被覆盖,但Git不会特意删除未被跟踪的文件。


如果我删除或修改了上一个提交中的文件,并检出到该提交,那么该文件将被还原,但这只是一种“副作用”? - Jack M
@JackM 实际上,在这种情况下,你会得到一个检出错误。Git 将强制您处理未决更改,因为它无法知道您的意图是什么。您只是忘了提交吗? - Sergio Tulentsev
@SergioTulentsev 这并不正确。Git没有报错,并将修改过的文件还原到之前的状态。 - Jack M
@JackM:当执行 git checkout . 或者 git checkout <ref> 时,你是指后者吗?我在描述后者。 - Sergio Tulentsev
如果我只运行 git checkout HEAD,它什么也不会做,但是也不会给我明显的错误提示(尽管它会打印出关于文件修改的消息,我猜这就是你的意思)。而如果我运行 git checkout HEAD .,它将会撤销所有对工作目录中已跟踪文件的更改。 - Jack M
@JackM:没错,那正是我想表达的。 - Sergio Tulentsev

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