1326

有时 git 建议取消暂存git rm --cached文件,有时git reset HEAD file. 我什么时候应该使用哪个?

编辑:

D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       a
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

D:\code\gt2>touch b

D:\code\gt2>git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       b
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add b

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#
4

14 回答 14

2120

git rm --cached <filePath> 不会取消暂存文件,它实际上会暂存从存储库中删除文件(假设它之前已经提交),但会将文件留在工作树中(留下未跟踪的文件)。

git reset -- <filePath>取消暂存给定文件的任何暂存更改。

也就是说,如果您git rm --cached在暂存的新文件上使用它,它基本上看起来就像您刚刚取消暂存它,因为它之前从未提交过。

更新 git 2.24
在这个较新版本的 git 中,您可以git restore --staged使用git reset. 请参阅git 文档

于 2011-08-02T22:03:13.717 回答
346

git rm --cached用于从索引中删除文件。如果文件已经在 repo 中,git rm --cached将从索引中删除文件,将其保留在工作目录中,并且提交现在也会将其从 repo 中删除。基本上,在提交之后,您将取消版本化文件并保留本地副本。

git reset HEAD file(默认情况下使用--mixed标志)的不同之处在于,在文件已经在 repo 中的情况下,它将文件的索引版本替换为 repo (HEAD) 中的版本,有效地取消对它的修改

在未版本化文件的情况下,它将取消暂存整个文件,因为该文件不在 HEAD 中。在这方面git reset HEAD filegit rm --cached它们是相同的,但它们不一样(如在 repo 中已有文件的情况下所解释的)

对于这个问题Why are there 2 ways to unstage a file in git?- 在 git 中做任何事情从来都不是只有一种方法。这就是它的美丽:)

于 2011-08-02T23:00:25.413 回答
139

很简单:

  • git rm --cached <file> 使 git 完全停止跟踪文件(将其留在文件系统中,与普通git rm* 不同)
  • git reset HEAD <file> unstages 自上次提交以来对文件所做的任何修改(但不会在文件系统中恢复它们,这与命令名称可能暗示的相反**)。该文件仍处于修订控制之下。

如果文件之前不在修订控制中(即,您正在取消暂存您刚刚git add编辑的文件),那么这两个命令具有相同的效果,因此它们的外观是“做某事的两种方式”。

* 请记住@DrewT 在他的回答中提到的关于以前提交到存储库git rm --cached的文件的警告。在这个问题的上下文中,对于刚刚添加但尚未提交的文件,没有什么可担心的。

** 因为它的名字,我很尴尬地害怕使用 git reset 命令——直到今天我仍然经常查看语法以确保我不会搞砸。(更新:我终于花时间总结git reset了 tldr 页面中的用法,所以现在我对它的工作原理有了更好的心智模型,并且当我忘记一些细节时可以快速参考。)

于 2014-10-17T21:16:01.983 回答
58

这个线程有点老了,但我还是想添加一点演示,因为它仍然不是一个直观的问题:

me$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   to-be-added
#   modified:   to-be-modified
#   deleted:    to-be-removed
#

me$ git reset -q HEAD to-be-added

    # ok

me$ git reset -q HEAD to-be-modified

    # ok

me$ git reset -q HEAD to-be-removed

    # ok

# or alternatively:

me$ git reset -q HEAD to-be-added to-be-removed to-be-modified

    # ok

me$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   to-be-modified
#   deleted:    to-be-removed
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   to-be-added
no changes added to commit (use "git add" and/or "git commit -a")

git reset HEAD(不带-q)给出关于修改文件的警告,其退出代码为 1,这将被视为脚本中的错误。

编辑:git checkout HEAD to-be-modified to-be-removed也适用于取消暂存,但从工作区中完全删除更改

更新 git 2.23.0:命令不时更改。现在,git status说:

  (use "git restore --staged <file>..." to unstage)

... 适用于所有三种类型的更改

于 2013-04-16T19:00:37.823 回答
37

如果您不小心暂存了您不想提交的文件,并希望确保保留更改,您还可以使用:

git stash
git stash pop

这会重置 HEAD 并重新应用您的更改,从而允许您重新暂存单个文件以进行提交。如果您忘记为拉取请求创建功能分支 ( git stash ; git checkout -b <feature> ; git stash pop),这也很有帮助。

于 2015-02-10T17:06:19.053 回答
16

如果有问题的文件已经在 repo 中并且在版本控制下(以前提交等),这两个命令有几个细微的区别:

  • git reset HEAD <file>在当前提交中取消暂存文件。
  • git rm --cached <file>也将为将来的提交取消暂存文件。在再次添加之前,它是未暂存的git add <file>

还有一个更重要的区别:

  • 在运行git rm --cached <file>并将您的分支推送到远程之后,任何从远程拉取您的分支的人都会从他们的文件中实际删除该文件,即使在您的本地工作集中该文件只是变得未跟踪(即没有从文件夹中物理删除)。

最后一个区别对于包含配置文件的项目很重要,其中团队中的每个开发人员都有不同的配置(即不同的基本 url、ip 或端口设置),因此如果您使用的git rm --cached <file>任何人拉动您的分支将不得不手动重新创建配置,或者您可以将您的配置发送给他们,他们可以将其重新编辑回他们的 ip 设置(等),因为删除只会影响人们从远程拉出您的分支。

于 2014-08-10T20:04:38.933 回答
11

1.

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a

(使用“git rm --cached ...”取消暂存)

  • git 是一个指针系统

  • 你还没有提交来改变你的指针

  • “从指向的存储桶中取出文件”的唯一方法是删除您告诉 git 监视更改的文件

2.

D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a

git 提交 -ma

  • 你承诺,'保存'

3.

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

(使用“git reset HEAD ...”取消暂存)

  • 您此时在代码中进行了提交
  • 现在您可以将指针重置为您的提交“恢复到上次保存
于 2016-09-08T16:26:07.657 回答
11

假设您stage通过 整个目录git add <folder>,但是您想从暂存列表(即运行时生成的列表git status)中排除一个文件并将修改保留在排除的文件中(您正在处理某些事情并且它还没有准备好提交,但是你不想失去你的工作......)。你可以简单地使用:

git reset <file>

运行时git status,您将看到无论您是什么文件,以及您reset仍在列表中unstaged的其余文件。addedstaged

于 2015-08-28T16:08:05.590 回答
8

在 > 2.2 的较新版本中,您可以使用git restore --staged <file_name>. 请注意这里如果您想一次取消暂存(移动到更改)您的文件,您可以使用上面的命令和您的文件名。例如

git restore --staged abc.html

现在,如果您想一次取消暂存所有文件,可以执行以下操作

git restore --staged .

请注意空格和点(.),这意味着考虑暂存所有文件。

于 2021-02-12T12:53:06.350 回答
6

只需使用:

git reset HEAD <filename>

这将取消暂存文件并保留您对其所做的更改,因此您可以反过来根据需要更改分支并将git add这些文件更改为另一个分支。保留所有更改。

于 2019-09-10T23:38:59.310 回答
5

我很惊讶没有人提到 git reflog ( http://git-scm.com/docs/git-reflog ):

# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}

reflog 是一个 git 历史记录,它不仅跟踪对 repo 的更改,还跟踪用户操作(例如,拉取、结帐到不同的分支等)并允许撤消这些操作。因此,与其取消暂存错误暂存的文件,您可以恢复到未暂存文件的位置。

这类似于git reset HEAD <file>但在某些情况下可能更细化。

抱歉 - 没有真正回答您的问题,而只是指出另一种方式来取消我经常使用的文件(我非常喜欢 Ryan Stewart 和 waldyrious 的答案。);)我希望它有所帮助。

于 2015-02-10T12:06:40.783 回答
5

仅适用于 2.23 及以上版本,

而不是这些建议,您可以使用 git restore --staged <file>顺序unstage文件。

于 2019-10-29T15:20:35.673 回答
4

在我看来,git rm --cached <file>从索引中删除文件而不从普通目录中删除它git rm <file>,就像操作系统rm <file>会从目录中删除文件而不删除其版本一样。

于 2013-06-06T12:06:01.867 回答
0

取消暂存文件(撤消 git add)

git restore --staged file.js # 将最新版本的 file.js 从 repo 复制到 index

丢弃本地更改

git restore file.js # 将 file.js 从索引复制到工作目录

git restore file1.js file2.js # 恢复工作目录下的多个文件

混帐恢复。# 丢弃所有本地更改(未跟踪的文件除外)

git clean -fd # 删除所有未跟踪的文件

于 2022-01-17T08:23:59.340 回答