【问题标题】:"git rm --cached x" vs "git reset head --​ x"?“git rm --cached x”与“git reset head --​x”?
【发布时间】:2011-08-13 12:35:51
【问题描述】:

GitRef.org - Basic:

git rm 将从 暂存区。这有点不同 来自git reset HEAD,其中“unstages” 文件。通过“取消舞台”,我的意思是它恢复了 集结区到那里 在我们开始修改之前。 另一方面,git rm 只是踢 文件完全离开舞台,所以 它不包含在下一个 提交快照,从而有效地 删除它。

默认情况下,git rm file 会将文件从暂存区完全删除,同时也会从您的磁盘 >(工作目录)中删除。要将文件保留在工作目录中,您可以使用git rm --cached。

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

【问题讨论】:

    标签: git git-reset git-index git-rm


    【解决方案1】:

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

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

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

    git 重置 [--<mode>] [<commit>]

    此表单将当前分支头重置为 <commit> 并且可能 更新索引(将其重置为 <commit> 的树)和 工作树取决于<mode>,它必须是其中之一 以下:
    --soft

    根本不接触索引文件或工作树(但会重置 前往<commit>,就像所有模式一样)。这让你所有的 已更改的文件“要提交的更改”,正如 git status 所说的那样。

    --混合

    重置索引但不重置工作树(即更改的文件 被保留但未标记为提交)并报告尚未提交的内容 更新。这是默认操作。

    --困难

    重置索引和工作树。对跟踪文件的任何更改 自 <commit> 以来的工作树被丢弃。

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

    git rm,另一方面,从工作目录和索引中删除一个文件,当您提交时,该文件也会从树中删除。但是,git rm --cached 会单独从索引中删除文件并将其保存在您的工作副本中。在这种情况下,如果文件之前已提交,那么您将索引设置为与树的 HEAD 和工作副本不同,因此 HEAD 现在具有以前提交的文件版本,索引根本没有没有文件,工作副本有它的最后修改。现在提交将同步索引和树,并且文件将从树中删除(使其在工作副本中未跟踪)。 当git add 用于添加新的(以前未跟踪的)文件时,git rm --cached 与git 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 --mixed。 git rm --cached 与 git add 相反的说法让我有些困惑。从字面上看,这是不正确的,可能会造成损坏。就我而言,我使用git add 将修改后的文件添加到暂存区,并希望与“那个添加”相反,而不是文件的初始添加。 +Greg Hewgill 的回答帮助我更清楚地了解了情况。
    • 我发现工作副本、树和工作树的使用有点混乱。工作树是工作副本还是树?
    • 正如@haridsv 提到的,说git rm --cached '与git add file 完全相反' 具有误导性。 git reset file 更接近于 git add file 的对立面。
    • @Nealv 迟到了,但对于其他发现此线程的人:工作副本、树和工作树都指的是同一个东西(在 git 的上下文中)。
    【解决方案2】:

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

    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"
    

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

    【讨论】:

    • 你能告诉我 HEAD 之后的双连字符是什么意思吗?
    • @yuva:-- 用于将命令选项与文件名分开。如果同时存在一个名为asd 的分支 和一个文件,那么git reset HEAD asd 将是不明确的。 -- 表示“后面的所有内容都是文件名”。
    • git reset HEAD <file> 是否与git rm --cached <file> 和git add --intent-to-add <file> 完全相同?
    • @alcoholisevil 否,特殊情况除外。请参阅this 优秀、简洁的答案。
    【解决方案3】:

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

    【讨论】:

    • 结合git rm --cached file 与git add 有点相反的概念(如其他答案中所述),这个答案对我来说很有意义,而且非常简洁。几乎和这条评论一样短;)
    • @rbatt 也将评论放在这里,并澄清,git rm --cached file 不是 git add file 的对立面。在您添加了一个新的、以前未跟踪的文件的特定情况下,该行为恰好与 git add file 相反。在所有其他情况下,git add file 的反义词是git reset HEAD file。 git 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.
    • 我用这个答案掌握了一切,而不是接受的答案很丰富
    猜你喜欢
    • 2021-04-02
    • 2016-02-24
    • 2021-07-04
    • 1970-01-01
    • 2023-03-16
    • 2012-09-15
    • 2018-01-13
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多