我使用命令错误地将文件添加到 Git :

git add myfile.txt

我还没跑呢git commit。我如何撤销这些修改,使这些修改不包含在承诺中?


当前回答

您想要 :

git rm --cached <added_file_to_undo>

理由:

当我刚开始做这个的时候,我第一次尝试

git reset .

(取消我最初添加的全部内容), 只是为了得到这个(不是这样的)有用信息:

fatal: Failed to resolve 'HEAD' as a valid ref.

结果发现,这是因为 HEAD ref (blanch?) 直到第一次承诺之后才存在。 这就是说,你会遇到跟我一样的初学者的问题, 如果你的工作流程像我的一样, 像是:

  1. Cd 我伟大的新项目目录 试探Git, 新的热度
  2. git init
  3. git add .
  4. git status

    ...很多垃圾卷轴 通过...

    该死,我不想加上这些

  5. google “ 未跳过 git 添加 ”

    找到堆叠溢出

  6. git reset .

    致命: 解决“ HEAD” 有效参考失败 。

更进一步发现a 窃听器记录与邮件列表中的无益对比。

正确的解决方案就在 Git 状态输出中( 是的, 我将它伪装成“ 废话 ” ) 。

...
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
...

解决的确是使用git rm --cached FILE.

请注意这里其他地方的警告-git rm删除本地文件的工作副本,但使用-- -- cooked。以下是git help rm:

--cached 使用此选项来卸载和从索引中删除路径。 工作树文件, 不论是否修改, 都会被左移 。

我开始使用

git rm --cached .

把所有东西都搬走,重新开始。虽然没有成功,因为当add .循环,结果rm需要满足的需求-r来重复。 叹气 。

git rm -r --cached .

好了,现在我回到我开始的地方 下次我再用-n以进行一个干燥的运行,然后观察将要增加什么:

git add -n .

在信任之前,我把所有东西都拉到一个安全的地方git help rm关于 The 的--cached你们不要毁灭任何物,如果我误译了它,

其他回答

使用使用git add -i以删除您即将承诺的添加文件 。 例如 :

添加您不想添加的文件 :

$ git add foo
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   foo
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]#

进入交互式添加以取消您的添加( 这里输入的 git 命令是“ r”( revert) , “ 1”( 列表返回显示的第一个条目) , “ return” 退出返回模式, 以及“ q” ( quit) :

$ git add -i
           staged     unstaged path
  1:        +1/-0      nothing foo

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> r
           staged     unstaged path
  1:        +1/-0      nothing [f]oo
Revert>> 1
           staged     unstaged path
* 1:        +1/-0      nothing [f]oo
Revert>> 
note: foo is untracked now.
reverted one path

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> q
Bye.
$

这就是你的证据 证明"foo"又回到了未追踪的名单上

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]
#       foo
nothing added to commit but untracked files present (use "git add" to track)
$

也许Git已经进化了 自从你提出问题之后

$> git --version
git version 1.6.2.1

现在,你可以试试:

git reset HEAD .

这应该就是你要找的

在接受的答案之外加一个, 如果你的错误添加的文档是巨大的, 你可能会注意到, 即使从索引中删除它与 ”git reset',它似乎仍然占据着空间.git目录。

这没什么可担心的;文件确实还在存储库中,但只是作为“空天体”而已。它不会被复制到其他存储库(通过克隆、推推),空间最终会被回收——也许不会很快。如果你急躁,你可以运行:

git gc --prune=now

更新更新更新(以下是我试图澄清最受重视的答案可能引起的混乱):

所以,这是真实的取消对联 联 年 月 日 月 日 月 月 日 月 月 日 月 月 月 日 月 月 日 月 月 日 月 月 月 日 月 月 日 月 月 月 日 月 的 月 月 月 日 月 月 日 月 的 月 月 月 月 日 月 月 月git add?

git reset HEAD <file> ?

git rm --cached <file>?

严格地说 如果我没弄错的话无 无.

git add 无法撤消- 安全,在一般情况下。

让我们首先回顾一下什么git add <file>实际上:

  1. 如果(如果)<file>原为之前未跟踪过, git add 添加到缓存中及其当前内容。

  2. 如果(如果)<file>原为已经跟踪, git add 保存当前内容在 Git 中, 此动作仍然被调用添加 添加, (不仅仅是更新更新更新因为文件的两个不同版本(笔记本)被视为两个不同的项目:因此,我们确实在缓存中添加一个新项目,最终将执行。

有鉴于此,问题略微模糊不清:

我使用命令错误地添加了文件...

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的评论)

撤消撤消git add用于未承诺更改的更改 :

git reset <file>

这将将文件从当前索引( “ 即将被承诺” 列表) 中删除, 而不更改其它内容 。


取消所有文件的所有更改 :

git reset

在旧的 Git 版本中,上述命令相当于git reset HEAD <file>git reset HEAD或将失效,如果HEAD未定义(因为你尚未在仓库中做出任何承诺)或模糊(因为你创建了一个分支,称为:HEAD这是你不该做的蠢事在Git 1.8.2中更改。,所以在现代版本的 Git 中,你可以使用上面的命令,甚至在你第一次做出承诺之前:

当您在历史中没有任何承诺时, “ 将重置” (没有选项或参数) 用于错误退出, 但它现在给了您一个空索引( 匹配不存在的重置, 您甚至没有在 ) 。

文 件:git 重设

缩略git reset命令帮助您修改中转区域或中转区域以及工作树。 Git 的手工能力与您想要的完全一样,意味着有时需要取消对您所要的修改的修改git add.

你可以通过拨打电话来做到这一点git reset HEAD <file to change>。您有两种选择可以完全消除变化。git checkout HEAD <file(s) or path(s)>是一种快速的方法 来消除改变你的中转区和工作树的改变。

但是要小心这个命令, 因为它会消除你工作树上的所有变化。 Git 根本不知道这些变化, 因为他们从未被执行过。 一旦你执行这个命令, 就没有办法让这些变化回来 。

您可支配的另一个命令是git reset --hard。它同样会破坏您的工作树,任何未承诺的改变或分阶段的改变在运行后都会丢失。运行中git reset -hard HEAD做同样的事情git checkout HEAD。它只是不需要文件或工作路径。

您可以使用--softgit reset。它将存储库重新设置为您指定和分阶段进行所有这些修改的承诺。您已经进行的任何修改都不会受到影响,工作树上的修改也不会受到影响。

最终,你可以使用--mixed将工作树重置,不进行任何修改。这也将取消任何正在准备的修改。