git reset –hard head`和git clean --force -d`vs`git checkout-之间有什么区别? [英] What is the difference between `git reset --hard head` vs `git clean --force -d ` vs `git checkout -- .` to discard local changes
问题描述
git reset --hard head
vs git clean --force -d
vs git checkout -- .
和git pull
之间的区别是什么?丢弃本地更改并从Git服务器存储库获取最新信息?
What are the differences between git reset --hard head
vs git clean --force -d
vs git checkout -- .
then git pull
to discard local changes and get the latest from the Git server repository?
推荐答案
As Ryan commented, git clean
is very different from the other two (which are pretty close, but not identical).
要详细比较git checkout -- .
和git reset --hard HEAD
,请参阅我对结帐-."和"git reset HEAD --hard"?请密切注意 index 的描述,因为这将使您了解下一部分.
For comparing, in gory detail, git checkout -- .
and git reset --hard HEAD
, see my answer to What is the difference between "git checkout -- ." and "git reset HEAD --hard"? Pay close attention to the descriptions of the index since that will inform you about the next part.
请记住,尽管您不能直接看到索引,但是 1 是下一次提交的内容.因此,至关重要的是要了解Git使用索引而不是工作树进行提交.通常,通过将索引与HEAD
提交进行比较来查看"索引就足够了:只要索引中的文件与HEAD
提交中的同一文件完全相同,而git status
则什么也不说.但是只要文件不同,git status
都会打印出一些东西.
Remember, although you cannot see the index directly,1 it's what goes into the next commit. As such it is crucial that you understand that Git makes commits using the index, not the work-tree. Usually, it's sufficient to "see" the index by comparing it to the HEAD
commit: wherever a file in the index is exactly the same as that same file in the HEAD
commit, git status
says nothing; but wherever a file is different, git status
prints something.
(注意:git status
还将索引与工作树分别进行比较.如果索引不同,则表示某些内容-除外用于未跟踪但被忽略的文件.仅适用于-根据定义,树文件可以被取消跟踪,因此毫无疑问索引文件是否被取消.总结它运行的两个git diff
时,git status
可以一次执行一次,在默认的长格式输出中,或一次全部显示在--short
输出中.)
(Note: git status
also, separately, compares the index to the work-tree. Where those are different, it says something—except for untracked-but-ignored files. Only work-tree files can be untracked, by definition, so there's no question about whether index files are untracked. When summarizing the two git diff
s it ran, git status
can either do it one at a time, in the default long-form output, or all at once, in the --short
output.)
1 实际上,您可以看到索引:运行git ls-index --stage
,Git会溢出整个内容. 2 实际上对于调试非常有用.但是,对于具有许多文件的大型存储库,它每天打印太多,而git status
是更好的工具.
1Actually, you can see the index: run git ls-index --stage
and Git will spill out the whole thing.2 This is actually quite useful for debugging. With a large repository with many files, though, it prints way too much for every-day use, and git status
is a much better tool.
2 实际上,您需要添加--debug
来获得 whole 内容,包括--assume-unchanged
和--skip-worktree
标志,即使这样,Git也会隐藏特殊内容.撤消您的条目.
2Actually you need to add --debug
to get the whole thing, including the --assume-unchanged
and --skip-worktree
flags, and even then Git hides the special undo entries from you.
在Git中,未跟踪的文件的定义实际上非常简单:它是不在索引中的文件.这几乎就是所有内容,尽管出于git clean
的目的,我们还需要另外一项,即文件是否也被忽略.
In Git, an untracked file is actually remarkably simple to define: it's a file that is not in the index. That's almost all there is to it, though for git clean
purposes, we also need one more item, namely, whether the file is ignored too.
如果文件被跟踪(位于索引中),则不能忽略它.这样的文件是Git已知的,因此git clean
将永远不会碰到它们:这不是它的工作;它的工作是删除部分或全部 untracked 文件.只能忽略未跟踪的文件,因此,未跟踪的文件要么被跟踪但不被忽略,要么被跟踪也被忽略.
A file cannot be ignored if it is tracked (is in the index). Such files are known to Git, so git clean
will never touch them: that's not its job; its job is to remove some or all of the untracked files. Only an untracked file can be ignored, so an untracked file is either untracked-but-not-ignored, or untracked-and-also-ignored.
默认情况下,根据--dry-run
和--force
之类的选项,git clean
会删除(或假装删除),只会删除那些也不会被忽略的未跟踪文件.
By default, git clean
will remove—or pretend to remove, depending on options like --dry-run
vs --force
—only those untracked files that are not also ignored.
使用-X
(大写X)选项,git clean
将仅删除(或一如既往地假装删除)那些忽略了 的未跟踪文件.
With the -X
(uppercase X) option, git clean
will remove (or as always, pretend to remove) only those untracked files that are ignored.
使用-x
(小写的x)选项,git clean
绕过所有忽略"规则,这意味着所有未跟踪的文件将自动属于未跟踪且不可忽略的类别.因此,git clean -f -x
将删除所有未跟踪的文件,即使那些通常被忽略的文件也是如此.
With the -x
(lowercase x) option, git clean
bypasses all the "ignore" rules, which means that all untracked files automatically fall into the untracked-and-not-ignored category. Thus, git clean -f -x
will remove all untracked files, even those that are normally ignored.
对于-d
,git clean
还将删除目录.根据定义,目录永远不会被跟踪, 3 ,因此所有目录实际上都是未跟踪的,但是它们是未跟踪的目录,而不是未跟踪的文件.但是,Git对子目录使用一种特殊的捷径处理,该子目录只包含未跟踪的文件(或者完全为空):除了枚举该目录 中的每个(未跟踪的)文件之外,Git都认为这是 4 git clean
命令通常将这些保留为空:
With -d
, git clean
will also remove directories. By definition, directories are never tracked,3 so all directories are effectively untracked—but they're untracked directories, not untracked files. Git uses a special short-cut treatment for a subdirectory that contains nothing but untracked files (or that is completely empty), though: instead of enumerating every (untracked) file in that directory, Git just considers this an "untracked directory".4 The git clean
command normally leaves these alone:
$ 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
本身:
The double question mark output from git status --short
indicates an untracked file or untracked directory. Since sub
is a directory with an untracked file in it, it shows up as an untracked directory. Running git clean -f
(or git clean -n
) shows that Git removes (or would remove) untr
, which is an untracked file that is not ignored; but Git does not remove either sub/subfile
or sub
itself:
$ git clean -f
Removing untr
在git clean
选项中添加-d
可使Git删除sub/subfile
和sub
:
Adding -d
to the git clean
options makes Git remove both sub/subfile
and sub
:
$ git clean -df
Removing sub/
(按照POSIX的要求,删除整个目录意味着首先删除其所有内容.)
(Removing the entire directory implies removing all of its contents first, as required by POSIX.)
在git clean
中添加路径名参数会将其清理限制为给定的路径名,这非常简单.
Adding pathname arguments to git clean
restricts its cleaning to the given pathnames, which is pretty straightforward.
请注意,还有一个特殊的特殊情况,即目录不会被忽略,但包含另一个Git存储库(无论是作为常规存储库,还是作为当前存储库的子模块):git clean -df
或git clean -dfx
不会删除此子存储库,但git clean -dff
或git clean -dffx
将会.
Note that there is yet another special corner case for a directory that is not ignored but contains another Git repository (whether as a regular repository, or as a submodule of the current repository): git clean -df
or git clean -dfx
will not remove this sub-repository, but git clean -dff
or git clean -dffx
will.
3 这实际上意味着您无法将目录添加到索引. 如果您尝试了足够的尝试,使用管道命令,可以诱骗Git使用正确的模式和名称来存储条目,但要使用数字在一定条件下,Git将该条目的模式从目录"更改为"gitlink",此后事情就变得很糟糕.(存在Gitlink条目用于存储子模块信息,通常在 中找到该条目一个Git索引.)
3What this really means is that you cannot add a directory to the index. 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 entries exist to store submodule information, and are normally found in a Git index.)
4 Git秘密地确实将stat
信息关于(至少一些)目录存储在索引中,作为性能改进.要点是,如果Git发现某个目录(例如sub
)仅包含未跟踪的文件,或者(递归地)仅包含未跟踪的文件的目录,则Git可以将其分类为在以后的工作树扫描中跳过" .加上Git的特殊忽略规则,这些规则可防止显式忽略"被忽略目录中的文件,如果自上次扫描以来未修改目录本身,Git可以避免在目录中扫描其他未跟踪但未被忽略的文件. (同样的想法-也就是说,如果目录本身未经修改,就不可能再添加任何新文件-甚至适用于包含跟踪文件的目录,尽管我不记得如果Git使用了事实,便会立即使用.)
4Git secretly does store stat
information about (at least some) directories in the index, as a performance hack. The gist of this is that if Git has found that some directory such as sub
contains nothing but untracked files or (recursively) directories with nothing but untracked files, Git can classify the thing as "to skip in future work-tree scans". This, plus Git's special ignore rules that prevent explicit "unignoring" of files within ignored directories, allow Git to avoid scanning the directory for additional untracked-but-not-ignored files if the directory itself is not modified since the last scan. (This same idea—that is, that if the directory itself is unmodified, no new files can possibly have been added to it—is even applicable to directories containing tracked files, although I don't remember offhand if Git uses the fact.)
这篇关于git reset –hard head`和git clean --force -d`vs`git checkout-之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!