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

Sen*_*ess 1109 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
#
Run Code Online (Sandbox Code Playgroud)

Rya*_*art 1809

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

git reset -- <filePath>取消暂存给定文件的任何分阶段更改.

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

  • 我会说`git rm --cached`取消暂存文件,但不会将其从工作目录中删除. (61认同)
  • “git status”现在建议:使用“git Restore --staged &lt;file&gt;...”取消暂存 (8认同)
  • 有了如此多的问题和答案表决权,我想说的显然是我们希望在git中有一个unstage命令。 (7认同)
  • 为什么我们不能使用“git stage”和“git unstage”,而不是添加晦涩命令的新变体? (6认同)
  • 要删除一个为了添加而暂存的文件以便它不再被暂存,肯定会被称为"为了添加而暂停一个文件",对吧?最终结果是_不是阶段式删除_,这是肯定的,因此我认为误解是完全可以理解的. (4认同)
  • 所以通常情况下,人们会使用`git rm --cached <filePath>`从**中删除一些文件后**意识到它应该从未进入过repo:所以最有可能运行这个命令然后添加相关文件到`gitignore`.我对么? (4认同)
  • git reset HEAD {文件名} (3认同)
  • git rm --cached 告诉 git 停止跟踪文件...这不是我想要的。我想暂时取消暂存一个文件,而不是停止一起跟踪它。:( (2认同)
  • 我希望每次我回过头来都能投赞成票。 (2认同)

man*_*lds 327

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中做任何事情.这就是它的美丽:)

  • 接受的答案和这个都很好,并解释了为什么你会使用一个与另一个.但他们没有直接回答*为什么*git提出两种不同方法的隐含问题.在OP的例子的第一种情况下,刚刚完成了一个git init.在这种情况下,git建议"git rm --cached",因为此时存储库中没有提交,因此HEAD无效."git reset HEAD - a"产生:"致命:未能将'HEAD'解析为有效的参考号." (6认同)
  • 使用'git checkout',你不会丢失你对文件所做的所有更改吗?这与取消暂存文件不同,除非我误解. (5认同)

wal*_*ous 120

很简单:

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

如果文件之前没有处于版本控制之下(即你是git add第一次取消刚刚编辑过的文件),那么这两个命令具有相同的效果,因此它们的外观是"两种做事方式" ".

*请记住@DrewT提到了他的答案,对于警告git rm --cached,这是一个文件的先前提交到仓库.在这个问题的上下文中,对于刚添加但尚未提交的文件,没有什么可担心的.

**我很害怕一个令人尴尬的长时间使用,因为它的名字的git的复位命令- ,还是在今天,我经常仰望的语法,以确保我不会搞砸.(更新:我终于花时间总结的使用git reset在tldr页面,所以我现在的它是如何工作的一个更好的心理模型,以及当我忘记一些细节的快速参考.)

  • 我真的不认为这个答案的[2015年8月4日编辑](http://stackoverflow.com/posts/26433550/revisions)是一个整体改进.它可能具有固定的技术正确性(我觉得没有资格对此进行评估),但我担心通过引入诸如"取消开始跟踪当前未跟踪的文件的必要性"这样的语言,它使得答案的语调变得难以理解",并使用像"索引"和"HEAD"这样的术语,正是那种吓跑初学者的东西.如果有人可以,请编辑以恢复更新的友好语言. (8认同)
  • 同意@waldyrious.最初的答案可能不是直接从git教科书中得出的,但它在足够的技术水平上回答了这个问题.技术细节应该在评论中澄清,而不是作为模糊原始意图的编辑. (5认同)

Dan*_*der 47

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

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")
Run Code Online (Sandbox Code Playgroud)

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

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


ive*_*ves 35

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

git stash
git stash pop
Run Code Online (Sandbox Code Playgroud)

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

  • 这是一个干净的解决方案,并且比输入"git rm"更不令人担忧 (2认同)

DEE*_*PAK 28

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

git restore --staged abc.html
Run Code Online (Sandbox Code Playgroud)

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

git restore --staged .
Run Code Online (Sandbox Code Playgroud)

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


Dre*_*ewT 15

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

  • git reset HEAD <file> 在当前提交中取消暂存文件.
  • git rm --cached <file>将取消暂存该文件以供将来提交.它是未分阶段的,直到再次添加git add <file>.

还有一个更重要的区别:

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

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


jim*_*kiz 10

比方说,你stage通过整个目录git add <folder>,但要排除来自上演列表中的文件(即运行时产生的列表git status),并保持已排除的文件中修改(您正在使用的东西,对提交它没有准备好,但你不想失去你的工作......).你可以简单地使用:

git reset <file>

当您运行时git status,您将看到无论您reset是哪个文件unstaged以及您added仍在staged列表中的其余文件.


Tim*_*art 9

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
Run Code Online (Sandbox Code Playgroud)

(使用"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
Run Code Online (Sandbox Code Playgroud)

git commit -ma

  • 你承诺,' 保存 '

3.

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

(使用"git reset HEAD ..."来取消演示)

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


小智 8

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

git Restore --staged file.js # 将 file.js 的最新版本从存储库复制到索引

放弃本地更改

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

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

git 恢复 . # 放弃所有本地更改(未跟踪的文件除外)

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

  • 值得一提的是,你需要 git 版本 &gt; 2.23.0 才能使用 `git Restore` (2认同)

Edg*_*ero 6

只需使用:

git reset HEAD <filename>

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


Ale*_*lex 5

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

# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}
Run Code Online (Sandbox Code Playgroud)

reflog是一个git历史记录,它不仅跟踪repo的更改,还跟踪用户操作(例如,pull,checkout到不同的分支等)并允许撤消这些操作.因此,不是取消暂停错误播放的文件,而是可以恢复到不放置文件的位置.

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

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


Kaa*_*ken 5

仅适用于 2.23 及以上版本,

除了这些建议之外,您还可以使用 git restore --staged <file>unstage处理文件。