为什么有两种方法可以在Git中取消暂存文件?

时间:2011-08-02 21:50:49

标签: git git-reset git-rm

有时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
#

13 个答案:

答案 0 :(得分:1673)

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

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

也就是说,如果你在一个新的文件中使用了git rm --cached,它基本上就像你刚刚从未提交它一样,因为它之前从未提交过。

答案 1 :(得分:320)

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

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

对于未版本控制的文件,由于HEAD中没有文件,因此它将取消整个文件的分级。在这方面,git reset HEAD filegit rm --cached是相同的,但它们不相同(如已在回购中的文件所述)

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

答案 2 :(得分:114)

很简单:

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

如果文件之前没有进行版本控制(即您第一次取消暂停刚刚git add编辑的文件),则这两个命令具有相同的效果,因此,这些存在的出现是两种做事的方式&#34;。

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

**由于它的名字,我害怕使用git reset命令的尴尬很长时间 - 而且今天我仍然经常查找语法,以确保我不会搞砸。 (更新:我终于花时间到了summarize the usage of git reset in a tldr page,所以现在我有一个更好的心理模型,它是如何工作的,以及我忘记一些细节时的快速参考。)

答案 3 :(得分:44)

这个帖子有点旧,但我还是想添加一些演示,因为它仍然不是一个直观的问题:

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也可用于取消暂停,但会从工作区中完全删除更改

答案 4 :(得分:32)

如果你不小心上演了你不想提交的文件,并且想要确定你保留更改,你也可以使用:

git stash
git stash pop

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

答案 5 :(得分:15)

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

  • git reset HEAD <file>在当前提交中取消暂存文件。
  • git rm --cached <file>将取消暂存文件以供将来提交。它已取消暂停,直到再次使用git add <file>添加。

还有一个更重要的区别:

  • 运行git rm --cached <file>并将您的分支推送到远程控制台后,任何从远程控制器拉出分支的人都会从其文件夹中删除 ACTUALLY 文件,即使在本地工作集中文件刚刚未跟踪(即没有从文件夹中物理删除)。

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

答案 6 :(得分:8)

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

git reset <file>

当您运行git status时,您会看到reset unstaged的任何文件added以及您staged的其余文件仍在this中{1}}列表。

答案 7 :(得分:8)

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 commit -m a

  • 您已提交,已保存'

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 ...”取消暂停)

  • 您此时在代码中提交了
  • 现在您可以重置指向提交的指针'恢复上次保存'

答案 8 :(得分: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的更改,还跟踪用户操作(例如,pull,checkout到不同的分支等)并允许撤消这些操作。因此,不要取消暂停错误播放的文件,而是可以恢复到不放置文件的位置。

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

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

答案 9 :(得分:3)

在我看来,git rm --cached <file>从索引中删除文件而不将其从普通git rm <file>同时执行这两者的目录中删除,就像操作系统rm <file>将删除目录中的文件,而不删除其版本控制。

答案 10 :(得分:3)

只需使用:

git reset HEAD <filename>

这会取消暂存文件并保留对它所做的更改,因此,如果需要,您可以依次更改分支,并将这些文件git add改为另一个分支。所有更改都会保留。

答案 11 :(得分:1)

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

git restore --staged abc.html

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

git restore --staged .

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

答案 12 :(得分:0)

代替这些建议,您可以使用 git restore --staged <file>以便unstage个文件。