是否可以撤消以下git命令:
git checkout -- .
我正在尝试删除添加到repo目录中但未暂存或未提交的文件。该命令似乎没有执行此操作,而是更改了一些其他文件。
更新:
未跟踪的文件和未暂存的文件之间存在区别。在这种情况下,我想找到一种丢弃未跟踪和未暂存文件的方法。当我运行git checkout -- .
时,我以为它将除去未跟踪的文件,但据我所知,它只能除去未暂存的文件。
答案 0 :(得分:2)
git checkout -- path
将从索引/登台区域复制到工作树如果您命名的 path
是目录,则Git将从其开始将其知道的所有文件(在索引/暂存区域中找到)复制到工作树中该目录及其所有子目录。
不过,要利用此答案,您需要了解每个文件的三个活动副本。
请记住,在Git中,每个文件始终有多达三个版本。例如,假设您在存储库中已提交名为README.txt
和a.ext
的文件。 README.txt
的三份和a.ext
的三份在任何给定时间都可以使用。三份副本中的两份采用特殊的仅Git格式。
如果我们使用git show
来访问仅Git格式文件的语法,则可以通过以下方式描述这三个副本:
HEAD index work-tree
--------------- ----------- ----------
HEAD:README.txt :README.txt README.txt
HEAD:a.ext :a.ext a.ext
如果您现在创建一个新的未跟踪文件b.dat
,则具有以下内容:
HEAD index work-tree
--------------- ----------- ----------
HEAD:README.txt :README.txt README.txt
HEAD:a.ext :a.ext a.ext
b.dat
在索引/暂存区域中尚无b.dat
的副本。在其他两个文件中,有 两个逻辑上分开的副本,尽管它们在HEAD
和索引中都是相同的。 。 (当它们相同时,Git会自动共享基础副本,因此不需要额外的空间。)
存储在工作树中的任何文件的任何副本都只是一个普通文件。您可以使用计算机执行的任何操作。 Git不在乎您如何处理此类文件。如果您询问Git有什么不同,Git 将告诉您工作树副本与索引副本不同。
git add path
将从工作树复制到临时区域此时,假设您使用任何喜欢的编辑器来修改README.txt
,该编辑器将编辑工作树副本(除非它非常熟悉Git,否则它将完全无法使用或触摸索引副本)。现在,工作树副本不同于索引副本。索引副本采用特殊的仅Git格式,可以进行下一次提交。
您现在将需要运行git add README.txt
,以将更新的工作树文件复制到索引中。完成此操作后,旧版本的README.txt
仍处于HEAD
提交中,也是仍采用特殊的仅Git格式,但是现在HEAD:README.txt
是与:README.txt
不同,而:README.txt
与README.txt
相同。
HEAD
提交副本是只读的;索引副本不是任何提交中的任何内容都无法更改。因此,您提交的README.txt
的副本和您提交的a.ext
的副本将永远安全地保存在存储库中 1 。索引/暂存区中的副本可能与HEAD
提交中的副本相同, 可以随时被覆盖。它的开始与HEAD
提交中的 2 相同,但是git add
从工作树到< / em>索引。
1 如果您放弃或删除提交(通常通过git reset
或git rebase -i
),则可能导致Git丢失冻结副本:冻结副本仅持续到只要包含它的提交即可。但是,大多数Git都是基于添加新提交而不删除旧提交的想法构建的。
2 如果您Checkout another branch when there are uncommitted changes on the current branch,您可以克服“签出或提交后HEAD和索引匹配”的正常情况。这个答案没有足够的空间来详细说明这些细节。
git commit
将所有索引副本冻结到一个新的提交中 git commit
的作用是将当时索引中的每个文件以当时索引中的格式获取,并将其冻结为只读的提交副本。此提交的文件集成为新的HEAD
提交。 git commit
完成运行并返回提示后,您将有一个新的提交,并且您的HEAD
提交和您的索引匹配-因为Git使新提交 from 为索引!
Git非常简单地定义了一个未跟踪文件:它是不在索引中的文件。就这样—就是所有的一切—但却有很强的后果:如果b.dat
不在索引中,则git commit
不会将其放入新提交中。而且,git checkout --
无法查找 b.dat
,因为它不在索引中,因此它不能覆盖工作树副本。
请注意,仅仅是因为某些文件存在于存储库中的 some 提交中,并不意味着文件已被跟踪!当且仅当该文件现在位于索引为 时,才会跟踪该文件。如果您运行git checkout
包含 的文件的提交,则 then (此时),Git会将提交中的文件复制到索引中,然后进入工作树。 当时将跟踪该文件。如果您随后从索引中明确删除文件,则那时将停止跟踪该文件。因此,您必须时刻牢记或测试索引中是否存在某些特定文件的副本,以了解是否已对其进行跟踪。
git checkout commit -- path
从提交复制,到索引和工作树在这里,通过git reset
,Git通过将多个不同的东西塞到一个命令中而变得过于复杂。当使用git checkout
with 路径,但没有提交或树说明符时,Git将从索引复制到工作树。当您同时使用git checkout
和和路径作为提交或树时,Git会将索引和的工作复制到 树。
git reset -- path
从提交提交,复制到索引,仅保留工作树 git reset
的这种特殊形式,与路径一起使用,从提交复制到索引/临时区域。请记住,索引已经包含所有跟踪文件的副本,因此这只是将它们与其他副本一起覆盖。默认情况下,git reset
用于获取文件的提交是HEAD
提交-因此,此副本将从有效的HEAD
副本复制到索引中。>
任何文件的工作树副本都保留下来。该文件存在于HEAD
提交中这一事实意味着该文件已被可能跟踪:取消跟踪该文件的唯一方法是:签出该提交,然后显式删除该提交。索引副本。在这种情况下,git reset -- path
将文件放回索引中,以便再次对其进行跟踪。
但是请注意,您可以使用git reset commit -- path
从特定的提交中复制文件。如果该文件不是在HEAD
提交中,则该文件很可能在您进行git reset
操作之前已被取消跟踪(不在索引中),但已被跟踪(在索引中)之后。这完全取决于您已经对索引进行了哪些更改。
运行git status
进行两次比较:
第一个比较是HEAD
vs索引。
HEAD
中的文件也可能在索引中(因此所有这些文件都被跟踪)。如果索引中的副本与HEAD
中的副本不同,则Git会调用准备提交的副本。如果索引中的副本与HEAD
中的副本相同,则文件本身仍会被跟踪和暂存-只是git status
不会困扰提及它。
这里的关键思想是,即使每次提交都是所有文件的完整快照,我们还是想知道关于 提交的内容:此提交有何不同之处因此,git status
告诉我们,如果我们采用当前暂存区(建议的新提交)并将其实际转换为新提交,会有什么不同。
第二个比较是索引与工作树。此处有什么不同之处是不上演提交阶段。
跟踪索引中的文件。对于那些与工作树中的内容相匹配的内容,git status
不用理会它们。对于那些不同的内容,git status
提及了它们,因为未上演提交。对于根本不在索引中但在工作树中是 的文件,Git抱怨说它们是未跟踪的。
再一次,这里的总体思路是,我们关心与前一个提交相比,每个提交实际上有什么不同。如果我们已取消暂存或什至未跟踪的文件与暂存副本不同(或缺少暂存副本),我们可以 使用git add
将它们复制到暂存区域。如果我们有一个与暂存的a.ext
完全相同的工作树a.ext
和与HEAD:a.ext
完全相同的工作树,那么我们可能不在乎,所以我们根本就不需要完全看到它。
要关闭绝对不应该提交的未跟踪文件,您可以列出这些未跟踪文件(按名称或全局模式,例如*.o
或*.pyc
)在.gitignore
指令中。这样可以防止Git自动将文件添加到git add .
或git add --all
中,也可以防止git status
发出抱怨。但是请注意,如果某个文件已经在索引中(无论它已经到达那里了),则在.gitignore
中列出该文件的名称或模式没有任何作用。。
复制文件的主要操作是:
git add path
:从工作树复制到索引git checkout -- path
:从索引复制到工作树git checkout commit -- path
:从 commit
复制到索引和工作树git reset [commit] -- path
:从 commit
(默认为HEAD
)复制到索引删除文件的主要操作是:
git add path
:如果 path
在索引中但在工作树中丢失,则从索引中删除git rm --cached path
:从索引中删除,但不从工作树中删除git rm path
:从索引和工作树中删除git reset [commit] -- path
:如果 path
中不包含 commit
(默认为HEAD
),则从索引中删除除这些以外,您还可以使用git commit --only paths
或git commit --include paths
触发一些特殊情况,但这些本质上等同于首先在这些路径上进行git add
。始终牢记索引,并注意git status
总结了索引的差异,而不是列出索引的内容,因此,如果您有30,000个大型文件项目,则只会看到很少有趣的文件,而不是全部30,000个文件。