ChatGPT解决这个技术问题 Extra ChatGPT

“git rm --cached x”与“git reset head -- x”?

GitRef.org - Basic

git rm 将从暂存区域中删除条目。这与“取消暂存”文件的 git reset HEAD 有点不同。 “取消暂存”是指它将暂存区域恢复到我们开始修改之前的状态。另一方面, git rm 只是将文件完全踢出舞台,因此它不会包含在下一个提交快照中,从而有效地删除它。默认情况下,一个 git rm 文件将从暂存区域中完全删除该文件,并从您的磁盘 >(工作目录)中删除该文件。要将文件保留在工作目录中,可以使用 git rm --cached。

但是 git rm --cached asdgit reset head -- asd 之间究竟有什么区别?


S
Sergei Tachenov

比如说,一个文件可以存在三个地方——(提交的)树、索引和工作副本。当您只是将文件添加到文件夹时,您就是将其添加到工作副本中。

当您执行 git add file 之类的操作时,您会将其添加到索引中。当你提交它时,你也将它添加到树中。

它可能会帮助您了解 git reset 中三个更常见的标志:

git reset [--] [] 此表单将当前分支头重置为 并可能根据 更新索引(将其重置为 的树)和工作树,它必须是以下之一: --soft 根本不接触索引文件或工作树(但将头部重置为 ,就像所有模式一样)。正如 git status 所说,这会使您所有更改的文件都“提交更改”。 --mixed 重置索引但不重置工作树(即,更改的文件被保留但未标记为提交)并报告尚未更新的内容。这是默认操作。 --hard 重置索引和工作树。自 以来对工作树中跟踪文件的任何更改都将被丢弃。

现在,当您执行 git reset HEAD 之类的操作时,您实际执行的是 git reset HEAD --mixed,它会将索引“重置”到您开始添加文件/向索引添加修改之前的状态(通过 git add) .在这种情况下,无论工作副本的状态是什么,您都没有对其进行任何更改,但是您以一种现在与树的 HEAD 同步的方式更改了索引。 无论 git add 用于暂存以前提交但已更改的文件,还是用于添加新的(以前未跟踪的)文件,git reset HEAD 都与 git add 完全相反。

另一方面,git rm 从工作目录和索引中删除一个文件,当您提交时,该文件也会从树中删除。但是,git rm --cached 会单独从索引中删除文件并将其保存在您的工作副本中。在这种情况下,如果文件之前已提交,那么您将索引设置为与树的 HEAD 和工作副本不同,因此 HEAD 现在具有以前提交的文件版本,索引根本没有没有文件,工作副本有它的最后修改。现在提交将同步索引和树,并且文件将从树中删除(使其在工作副本中未跟踪)。 当使用 git add 添加新的(以前未跟踪的)文件时,git rm --cachedgit add 完全相反(与 git reset HEAD 几乎相同)。

Git 2.25 为这些情况引入了一个新命令 git restore,但从 Git 2.28 开始,它在手册页中被描述为“实验性”,因为行为可能会改变。


我注意到在 git rm --cached 之后,git diff 命令没有显示任何差异,但 git diff --cached 显示了差异,就好像它仍然被缓存一样。但是 git status 将文件显示为 Untracked。好像有点违和
没关系...我应该使用 git reset --mixedgit rm --cachedgit add 相反的说法让我有点困惑。从字面上看,这是不正确的,可能会造成损坏。就我而言,我使用 git add 将修改后的文件添加到暂存区,并希望与“那个添加”相反,而不是文件的初始添加。 +Greg Hewgill 的回答帮助我更清楚地了解情况。
我发现工作副本、树和工作树的使用有点令人困惑。工作树是工作副本还是树?
正如@haridsv 提到的,说 git rm --cached '与 git add file 完全相反' 具有误导性。 git reset file 更接近于 git add file 的反面。
@Nealv 迟到了,但对于其他找到这个线程的人来说:工作副本、树和工作树都指的是同一件事(在 git 的上下文中)。
G
Greg Hewgill

也许一个例子会有所帮助:

git rm --cached asd
git commit -m "the file asd is gone from the repository"

相对

git reset HEAD -- asd
git commit -m "the file asd remains in the repository"

请注意,如果您没有更改任何其他内容,则第二次提交实际上不会做任何事情。


你能告诉我这个双连字符 - 在 HEAD 之后的实际含义是什么吗?
@yuva:-- 用于将命令选项与文件名分开。如果同时有一个名为 asdbranch 和一个 file,那么 git reset HEAD asd 将是不明确的。 -- 表示“这之后的所有内容都是文件名”。
git reset HEAD <file> 是否与 git rm --cached <file>git add --intent-to-add <file> 完全相同?
@alcoholisevil 不,除非在特殊情况下。请参阅 this 出色、简洁的答案。
y
yuriks

git rm --cached file 将从舞台中删除文件。也就是说,当您提交时,文件将被删除。 git reset HEAD -- file 将简单地将暂存区域中的文件重置为它在 HEAD 提交时的状态,即,将撤消您自上次提交以来对其所做的任何更改。如果该更改恰好是新添加的文件,那么它们将是等效的。


结合git rm --cached filegit add相反的概念(如其他答案中所述),这个答案对我来说很有意义,而且非常简洁。几乎和这条评论一样短;)
@rbatt 也将评论放在这里,并澄清,git rm --cached file 不是 git add file 的对立面。在您添加了一个新的、以前未跟踪的文件的特定情况下,该行为恰好与 git add file 相反。在所有其他情况下,git add file 的对立面是 git reset HEAD filegit reset HEAD file 在第一种情况下(添加未跟踪的文件)也会反转 git add file,并且在每种情况下,如果您想反转 git add,这就是 git 建议这样做的原因。
您的回答有问题,如果更改是“添加文件”,则使用 git reset HEAD file 不会有任何效果,您只会得到 fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
我用这个答案而不是接受的答案来掌握一切