除了已接受的答案之外,如果您错误添加的文件很大,您可能会注意到,即使在使用“git reset”将其从索引中删除后,它似乎仍会占用@987654322 中的空间@目录。
这没什么好担心的;该文件确实仍在存储库中,但仅作为“松散对象”。它不会被复制到其他存储库(通过克隆、推送),并且空间最终会被回收——尽管可能不会很快。如果你着急,你可以跑:
git gc --prune=now
更新(以下是我试图消除一些可能由最受好评的答案引起的混淆):
那么,git add 真正的撤消是什么?
git reset HEAD <file>?
或
git rm --cached <file>?
严格来说,如果我没记错的话:无。
git add 无法撤消 - 一般而言是安全的。
让我们首先回顾一下git add <file> 的实际作用:
如果<file>以前没有被跟踪,git add将其添加到缓存中及其当前内容。
如果<file>已被跟踪,git add保存当前内容(快照、版本)到缓存。在 Git 中,此操作仍称为 add,(不仅仅是 update 它),因为文件的两个不同版本(快照)被视为两个不同的项目:因此,我们确实正在向缓存中添加一个新项目,最终将在以后提交。
鉴于此,这个问题有点模棱两可:
我错误地使用命令添加了文件...
OP 的场景似乎是第一个(未跟踪的文件),我们希望“撤消”从跟踪的项目中删除文件(不仅仅是当前内容)。 如果是这种情况,那么运行git rm --cached <file>就可以了。
我们也可以运行git reset HEAD <file>。这通常更可取,因为它适用于两种情况:当我们错误地添加了已跟踪项目的版本时,它也会撤消。
但有两个注意事项。
首先:(如答案中所指出的)只有一种情况 git reset HEAD 不起作用,但 git rm --cached 起作用:一个新的存储库(没有提交)。但是,实际上,这实际上是一个无关紧要的案例。
第二:注意git reset HEAD 不能神奇地恢复以前缓存的文件内容,它只是从 HEAD 重新同步它。如果我们被误导的git add 覆盖了之前暂存的未提交版本,我们将无法恢复它。这就是为什么严格来说,我们无法撤消 [*]。
例子:
$ git init
$ echo "version 1" > file.txt
$ git add file.txt # First add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add file.txt # Stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff file.txt
-version 2
+version 3
$ git add file.txt # Oops we didn't mean this
$ git reset HEAD file.txt # Undo?
$ git diff --cached file.txt # No dif, of course. stage == HEAD
$ git diff file.txt # We have irrevocably lost "version 2"
-version 1
+version 3
当然,如果我们只是遵循通常的惰性工作流程,只为添加新文件执行“git add”(案例 1),并且我们通过提交 git commit -a 命令更新新内容,这并不是很关键。
*(编辑:以上内容实际上是正确的,但仍然可能有一些稍微有点骇人听闻/令人费解的方法来恢复已暂存但未提交然后被覆盖的更改 - 请参阅 Johannes Matokic 和 iolsmit 的 cmets)