如何在提交之前撤销“git add”?

我错误地使用以下命令添加文件:

git add myfile.txt 

我还没有运行git commit 。 有没有办法撤消这个,所以这些文件不会被包含在提交?

你可以在提交之前撤销git add

 git reset <file> 

这将从当前索引(“即将提交”列表)中删除,而不会改变任何其他内容。

您可以使用

 git reset 

没有任何文件名称来取消所有应有的更改。 当在合理的时间内逐一列出太多的文件时,这可以派上用场。

在旧版本的Git中,上面的命令分别等同于git reset HEAD <file>git reset HEAD ,如果HEAD未定义(因为您还没有在您的repo中进行任何提交)或模糊(因为您创build了一个名为HEAD的分支,这是你不应该做的一件愚蠢的事情)。 这在Git 1.8.2中已经改变了 ,所以在现代版本的Git中,甚至可以在进行第一次提交之前使用上面的命令:

“git reset”(没有选项或参数)用于在历史logging中没有任何提交时出错,但它现在会给你一个空索引(以匹配不存在的甚至不存在的提交)。

你要:

 git rm --cached <added_file_to_undo> 

推理:

当我是新的,我第一次尝试

 git reset . 

(撤消我的整个初始添加),只有得到这个(不那么)有用的消息:

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

事实certificate,这是因为HEAD ref(branch?)直到第一次提交之后才存在。 也就是说,如果您的工作stream程与我的工作stream程类似,您将遇到与我一样的初学者问题:

  1. 光盘到我的伟大的新项目目录尝试Git,新的热点
  2. git init
  3. git add .
  4. git status

    …很多废话卷轴…

    =>该死的,我不想把所有这些都加进去。

  5. 谷歌“撤消git添加”

    =>find堆栈溢出 – 耶

  6. git reset .

    =>致命:无法parsing“HEAD”作为有效的参考。

它进一步certificate,有一个错误logging在邮件列表中对此没有帮助。

而且正确的解决scheme就在Git状态输出中(这是的,我把它当作垃圾)

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

而解决scheme的确使用git rm --cached FILE

请注意这里的其他地方的警告 – git rm会删除您的本地文件的工作副本,但是如果您使用–cached ,则不会 。 下面是git help rm的结果:

–cached使用此选项可以取消仅从索引中删除path。 工作树文件,无论是否修改,都将被留下。

我继续使用

 git rm --cached . 

删除一切,然后重新开始。 虽然没有工作,因为当add . 是recursion的,结果rm需要-rrecursion。 叹。

 git rm -r --cached . 

好吧,现在我回到我开始的地方。 下次我要用-n做一个干运行,看看会增加什么:

 git add -n . 

我把所有东西都压缩到了一个安全的地方,然后再相信git help rm关于--cached没有破坏任何东西(如果我拼错了它会怎么样)。

如果你input:

 git status 

git会告诉你什么是上演等,包括如何取消的指示:

 use "git reset HEAD <file>..." to unstage 

我发现git在推动我在这样的情况下做正确的事情做得相当不错。

注意:最近的git版本(1.8.4.x)已经改变了这个消息:

 (use "git rm --cached <file>..." to unstage) 

澄清: git add将当前工作目录的变化移动到临时区域 (索引)。

这个过程被称为分期 。 所以,最自然的命令来改变(更改文件)是显而易见的:

 git stage 

git add只是一个更容易为git stage键入别名

可惜没有git unadd也没有git unadd命令。 相关的一个很难猜测或记住,但很明显:

 git reset HEAD -- 

我们可以很容易地为此创build一个别名:

 git config --global alias.unadd 'reset HEAD --' git config --global alias.unstage 'reset HEAD --' 

最后,我们有了新的命令:

 git add file1 git stage file2 git unadd file2 git unstage file1 

我个人使用更短的别名:

 git a #for staging git u #for unstaging 

除了被接受的答案,如果你错误地添加的文件是巨大的,你可能会注意到,即使通过' 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 会将其 git add 到caching中 ,并将其添加到caching中

  2. 如果<file> 已经跟踪git add 将当前内容 (快照,版本)保存到caching中。 在GIT中,这个动作仍然被称为add (不仅仅是更新它),因为一个文件的两个不同的版本(快照)被认为是两个不同的项目:因此,我们确实增加了一个新的项目到caching中,最终稍后提交。

有鉴于此,这个问题有些模糊:

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

OP的scheme似乎是第一个(未跟踪的文件),我们希望“撤消”从跟踪的项目中删除文件(不仅仅是当前的内容)。 如果是这种情况,那么可以运行git rm --cached <file>

我们也可以运行git reset HEAD <file> 。 这通常是可取的,因为它在两种情况下都可以工作:当我们错误地添加已经跟踪的项目的版本时,它也会进行撤销。

但有两个警告。

首先:(正如答案中指出的那样)只有一个git reset HEAD不起作用的场景,但是git rm --cached做了:一个新的仓库(不提交)。 但是,这实际上是一个几乎不相干的案例。

第二:请注意, git reset HEAD不能奇迹般地恢复以前caching的文件内容,它只是从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 lost irrevocably "version 2" -version 1 +version 3 

当然,如果我们按照通常的懒惰工作stream程来做“git add”来添加新文件(情况1),那么这并不是非常重要,我们通过commit, git commit -a命令来更新新的内容。

 git rm --cached . -r 

将“递增”从当前目录递增添加

 git gui 

并手动删除所有的文件,或select所有的文件,然后从提交button点击停止

Git拥有可以想象的每一个动作的命令,但需要广泛的知识才能把事情做好,因为它最好是反直觉的。

你以前做过什么:

  • 更改了一个文件并使用了git add . ,或者git add <file>

你要什么:

  • 从索引中删除文件,但保留版本,并保留工作副本中未提交的更改:

     git reset head <file> 
  • 将文件重置为HEAD的最后一个状态,撤消更改并将其从索引中删除:

     # Think `svn revert <file>` IIRC. git reset HEAD <file> git checkout <file> # If you have a `<branch>` named like `<file>`, use: git checkout -- <file> 

    这是必要的,因为git reset --hard HEAD将无法使用单个文件。

  • 从索引和版本中删除<file> ,保留工作副本中未更改版本的文件:

     git rm --cached <file> 
  • 完全从工作副本和版本中删除<file>

     git rm <file> 

如果你在初始提交,你不能使用git reset,只需声明“Git破产”并删除.git文件夹,并重新开始

这个问题没有明确提出。 原因是git add有两个含义:

  1. 添加一个新的文件到暂存区,然后用git rm --cached file撤销。
  2. 添加一个修改后的文件到暂存区,然后用git reset HEAD file撤销。

如果有疑问,请使用

 git reset HEAD file 

因为它在两种情况下都做了预期的事情。

警告:如果你在被修改的文件(在版本库中存在的git rm --cached file上执行了git rm --cached file ,那么该文件将在git commit上被删除! 它仍然存在于你的文件系统中,但是如果有其他人提交你的提交,文件将从他们的工作树中被删除。

git status会告诉你,如果该文件是一个新的文件修改

 On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: my_new_file.txt modified: my_modified_file.txt 

根据其他许多答案,你可以使用git reset

但:

我发现这个很棒的小贴子实际上为git unadd添加了Git命令(以及别名):请参阅git unadd了解详细信息或..

只是,

 git config --global alias.unadd "reset HEAD" 

现在你可以

 git unadd foo.txt bar.txt 

git remove或者git rm可以使用--cached标志。 尝试:

 git help rm 

使用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) # [...]# 

进入交互式添加撤消你的添加(在这里input的命令是“r”(还原),“1”(列表中的第一个条目恢复显示),“返回”退出恢复模式,“q” (放弃):

 $ 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. $ 

而已! 这是你的certificate,显示“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) $ 

当您开始一个新的项目时,以下是避免这个棘手问题的方法:

  • 为您的新项目创build主目录。
  • 运行git init
  • 现在创build一个.gitignore文件(即使它是空的)。
  • 提交你的.gitignore文件。

如果你没有任何提交,Git会让你很难做到git reset 。 如果你只是为了创build一个小的初始提交,然后你可以git add -Agit reset多次,只要你想要的一切正确。

这种方法的另一个优点是,如果您稍后遇到行结束的麻烦并需要刷新所有文件,很容易:

  • 看看最初的提交。 这将删除所有的文件。
  • 然后再次检查您最近的提交。 这将使用您当前的行结束设置来检索文件的新副本。

也许自从你发布你的问题后,Git已经发展了。

 $> git --version git version 1.6.2.1 

现在,你可以尝试:

 git reset HEAD . 

这应该是你在找什么。

请注意,如果您未能指定修订,则必须包含分隔符。 从我的控制台的示例:

 git reset <path_to_file> fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree. Use '--' to separate paths from revisions git reset -- <path_to_file> Unstaged changes after reset: M <path_to_file> 

(git版本1.7.5.4)

撤销已经添加的文件是相当容易的,为了重置已经添加的myfile.txt ,使用:

 git reset HEAD myfile.txt 

说明:

在你创build不需要的文件之后,为了撤消,你可以做git resetHead是你本地文件的头部,最后一个参数是文件的名字。

我在下面的图片中为您创build了更多步骤中的步骤,包括在这些情况下可能发生的所有步骤:

在这里输入图像描述

要从暂存区域中删除新文件(只有在新文件的情况下),如上所示:

 git rm --cached FILE 

使用rm – 只适用于意外添加的新文件。

使用*命令一次处理多个文件

 git reset HEAD *.prj git reset HEAD *.bmp git reset HEAD *gdb* 

等等

要重置特定文件夹(及其子文件夹)中的每个文件,可以使用以下命令:

 git reset * 

只要键入git reset它将恢复回来,这就像你从来没有inputgit add . 自从你上次提交以来。 确保你已经承诺过。

假设我创build了一个新文件newFile.txt

在这里输入图像描述

假设我不小心添加了文件, git add newFile.txt

在这里输入图像描述

现在我想撤消这个添加,在提交之前, git reset newFile.txt

在这里输入图像描述

这个命令将会消除您的更改:

 git reset HEAD filename.txt 

你也可以使用

 git add -p 

添加部分文件。

要撤消git添加使用

git reset filename

我很惊讶,没有人提到互动模式:

 git add -i 

select选项3以取消添加文件。 在我的情况下,我经常想添加多个文件,在交互模式下,您可以使用这样的数字来添加文件。 这将采取所有,但4:1,2,3,5

要select一个序列,只需键入1-5从1到5。

Git临时文件

在SourceTree中,您可以通过gui轻松完成此操作。 您可以检查sourcetree使用哪个命令来取消文件。

我创build了一个新的文件,并将其添加到混帐。 然后我使用SourceTree GUI对其进行分类。 这是结果:

分期档案[08/12/15 10:43]
git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q – path / to / file / filename.java

SourceTree使用reset取消新文件。

 git reset filename.txt 

将从当前索引中删除名为filename.txt的文件,即“将要提交的”区域,而不更改其他任何内容。

最直观的解决scheme之一是使用SourceTree 。

您只需拖放文件即可 在这里输入图像描述

git add myfile.txt #这会将您的文件添加到提交列表中

恰恰相反,这个命令是,

 git reset HEAD myfile.txt # this will undo it. 

所以,你会处于以前的状态。 指定将再次在未跟踪的列表(以前的状态)。

它会重置您的头与该指定的文件。 所以,如果你的头没有这个意思,它会重置它

 git reset filename.txt 

将从当前索引中删除名为filename.txt的文件,即“将要提交的”区域,而不更改其他任何内容。