繁体   English   中英

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

[英]Why are there two ways to unstage a file in Git?

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

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

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

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

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

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?取消Why are there 2 ways to unstage a file in git? - 在 git 中做任何事情的方法从来都不是只有一种。 这就是它的美妙之处:)

很简单:

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

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

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

** 由于它的名字,我很长时间都害怕使用 git reset 命令——直到今天我仍然经常查看语法以确保我没有搞砸。 更新:我终于花时间在 tldr 页面中总结了git reset的用法,所以现在我对它的工作方式有了一个更好的心理模型,以及当我忘记一些细节时的快速参考。)

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

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)

... 适用于所有三种类型的变化

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

git stash
git stash pop

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

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

  • git reset HEAD <file>在当前提交中取消暂存文件。
  • git rm --cached <file>也将取消git rm --cached <file>文件以备将来提交。 在使用git add <file>再次git add <file>它是未git add <file>

还有一个更重要的区别:

  • 运行后git rm --cached <file> ,并把你的分支到远程,任何人从远程拉你的分公司将充分利用自己的文件夹中实际删除文件,即使在您的本地工作仅有变成未被跟踪的文件(即不从文件夹中物理删除)。

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

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

git reset <file>

当您运行git status ,您将看到您reset任何文件unstaged ,而您added的其余文件仍在staged列表中。

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

  • 您此时在代码中进行了提交
  • 现在您可以将指针重置为您的提交“恢复到上次保存

只需使用:

git reset HEAD <filename>

这会取消暂存文件并保留您对它所做的更改,因此您可以反过来,如果需要,更改分支,然后git add这些文件git add到另一个分支。 保留所有更改。

我很惊讶没有人提到 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 的答案。);)我希望它有所帮助。

仅适用于 2.23 及以上版本,

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

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

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

git restore --staged abc.html

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

git restore --staged .

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

取消暂存文件(撤消 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 # 删除所有未跟踪的文件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM