git reset --hard head
与git clean --force -d
vs git checkout -- .
然后git pull
之间有什么区别可以放弃本地更改并从Git服务器存储库中获取最新信息?
答案 0 :(得分:4)
作为Ryan commented,git clean
与其他两个非常不同(非常接近,但不完全相同)。
要进行比较,请详细说明git checkout -- .
和git reset --hard HEAD
,请参阅我对What is the difference between "git checkout -- ." and "git reset HEAD --hard"?的回答。密切关注索引的说明,因为那样告诉你下一部分。
请记住,虽然你不能直接看索引, 1 它下一次提交的内容。因此,您必须了解Git使用索引提交,而不是使用工作树。通常,它足以“看到"通过将它与HEAD
提交进行比较的索引:索引中的文件与HEAD
提交中的同一文件完全相同,git status
什么也没说;但是在文件不同的地方,git status
会打印一些东西。
(注意:git status
也单独将索引与工作树进行比较。如果不同,它会为未跟踪但被忽略的文件显示除之外的内容。根据定义,工作树文件可以不被跟踪,因此对索引文件是否未被跟踪毫无疑问。当总结它运行的两个git diff
时,git status
可以在默认长格式输出中的时间,或--short
输出中的所有时间。)
1 实际上,你可以看到索引:运行git ls-index --stage
并且Git将溢出整个事情。 2 这实际上对调试非常有用。但是,对于包含许多文件的大型存储库,它会为每天使用打印太多,git status
是一个更好的工具。
2 实际上你需要添加--debug
来获取整个的东西,包括--assume-unchanged
和--skip-worktree
标志,以及即便如此,Git也会隐藏你的特殊撤消条目。
git clean
仅删除(部分或全部)未跟踪的文件在Git中,未跟踪的文件实际上非常容易定义:它是不在索引中的文件。这几乎就是它的全部内容,但是出于git clean
的目的,我们还需要一个项目,即文件是否也被忽略。
如果跟踪文件(在索引中),则无法忽略该文件。这些文件是Git已知的,因此git clean
永远不会触及它们:那不是它的工作;它的工作是删除部分或全部未跟踪的文件。只有未跟踪的文件才能被忽略,因此未跟踪的文件要么未被跟踪,要么被忽略,或者未被跟踪,也被忽略。
默认情况下,git clean
会删除或假装删除,具体取决于--dry-run
vs --force
等选项 - 仅限那些未被忽略的未跟踪文件。
使用-X
(大写X)选项,git clean
将删除(或一如既往地假装删除)仅 忽略的未跟踪文件。
使用-x
(小写x)选项,git clean
会绕过所有"忽略"规则,这意味着所有未跟踪的文件都会自动落入未跟踪和未被忽略的类别中。因此,git clean -f -x
将删除所有未跟踪的文件,即使是那些通常被忽略的文件。
使用-d
,git clean
也会删除目录。根据定义,永远不会跟踪目录, 3 所以所有目录都是有效的未跟踪 - 但是它们未被跟踪的目录,而不是未跟踪的文件。 Git对一个只包含未跟踪文件(或完全为空)的子目录使用了一种特殊的快捷处理方法,但是:Git只考虑这个目录,而不是枚举该目录中的每个(未跟踪)文件。 "未跟踪的目录"。 4 git clean
命令通常只留下这些:
$ mkdir tt
$ cd tt
$ git init
Initialized empty Git repository in ...
$ echo for testing git clean > README
$ git add README
$ touch untr
$ mkdir sub
$ touch sub/subfile
$ git status --short
A README
?? sub/
?? untr
git status --short
的双重问号输出表示未跟踪的文件或未跟踪的目录。由于sub
是一个包含未跟踪文件的目录,因此它显示为未跟踪的目录。运行git clean -f
(或git clean -n
)表示Git删除(或将删除)untr
,这是一个未被忽略的未跟踪文件;但是Git不会删除sub/subfile
或 sub
本身:
$ git clean -f
Removing untr
将-d
添加到git clean
选项会使Git删除sub/subfile
和sub
:
$ git clean -df
Removing sub/
(删除整个目录意味着首先根据POSIX的要求删除所有内容。)
向git clean
添加路径名参数会将其清理限制为给定的路径名,这非常简单。
请注意,对于未被忽略但包含另一个Git存储库(无论是作为常规存储库还是作为当前存储库的子模块)的目录还有另一个特殊情况:git clean -df
或{{1不会删除此子存储库,但git clean -dfx
或git clean -dff
将。
3 这实际意味着您无法将目录添加到索引中。 If you try hard enough, using the plumbing commands, you can trick Git into storing an entry with the right mode and name, but under a number of conditions, Git changes this entry's mode from "directory" to "gitlink", after which things go quite badly awry.(Gitlink条目用于存储子模块信息, 通常在Git索引中找到。)
4 Git暗中 存储git clean -dffx
信息关于(至少某些)目录中的索引,作为性能黑客。这样做的要点是,如果Git发现某些目录(例如stat
)只包含未跟踪文件或(递归)目录,只包含未跟踪文件,Git可以将该事物归类为"以便将来跳过工作树扫描"。这个加上Git的特殊忽略规则可以防止明确的" unignoring"忽略目录中的文件,如果自上次扫描后目录本身未被修改,则允许Git避免扫描目录以查找其他未跟踪但未被忽略的文件。 (同样的想法 - 也就是说,如果目录本身未被修改,可能没有新的文件添加到它 - 甚至适用于包含跟踪文件的目录,虽然我不记得Git使用的事实。)