reset

git reset HEAD 取消缓存已缓存的内容

git reset 可能是人类写的最费解的命令了。 我用 Git 有些年头了,甚至还写了本书,但有的时候还是会搞不清它会做什么。 所以,我只说三个明确的,通常有用的调用。请你跟我一样尽管用它 —— 因为它可以很有用。

在此例中,我们可以用它来将不小心缓存的东东取消缓存。假设你修改了两个文件,想要将它们记录到两个不同的提交中去。 你应该缓存并提交一个,再缓存并提交另外一个。如果你不小心两个都缓存了,那要如何才能_取消_缓存呢? 你可以用 git reset HEAD -- file。 技术上说,在这里你不需要使用 -- —— 它用来告诉 Git 这时你已经不再列选项,剩下的是文件路径了。 不过养成使用它分隔选项与路径的习惯很重要,即使在你可能并不需要的时候。

好,让我们看看取消缓存是什么样子的。这里我们有两个最近提交之后又有所改动的文件。我们将两个都缓存,并取消缓存其中一个。

$ git status -s
 M README
 M hello.rb
$ git add .
$ git status -s
M  README
M  hello.rb
$ git reset HEAD -- hello.rb
Unstaged changes after reset:
M hello.rb
$ git status -s
M  README
 M hello.rb

现在你执行 git commit 将只记录 README 文件的改动,并不含现在并不在缓存中的 hello.rb

如果你好奇,它实际的操作是将该文件在“索引”中的校验和重置为最近一次提交中的值。 git add 会计算一个文件的校验和,将它添加到“索引”中, 而 git reset HEAD 将它改写回原先的,从而取消缓存操作。

如果你想直接执行 git unstage,你可以在 Git 中配置个别名。 执行 git config --global alias.unstage "reset HEAD" 即可。 一旦执行完它,你就可以直接用 git unstage [file]作为代替了。

如果你忘了取消缓存的命令,Git 的常规 git status 输出的提示会很有帮助。 例如,在你有已缓存的文件时,如果你不带 -s 执行 git status,它将告诉你怎样取消缓存:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#   modified:   README
#   modified:   hello.rb
#

简而言之,执行 git reset HEAD 以取消之前 git add 添加,但不希望包含在下一提交快照中的缓存。

文章导航