如何在提交前撤销'git add'?

我错误地用命令将文件添加到Git上。

git add myfile.txt

我还没有运行git commit。有什么办法可以撤销这一点,使这些文件不会被包含在提交中?

对该问题的评论 (10)
解决办法

你可以在提交前撤消git add,用

git reset 

这将把它从当前索引(即将提交的列表)中删除,而不会改变其他东西。

你可以使用

git reset

不加任何文件名来解除所有应得的修改。当有太多的文件无法在合理的时间内逐一列出时,这个方法就会很方便。

在旧版本的Git中,上述命令分别等同于git reset HEADgit reset HEAD,如果HEAD未定义(因为你的仓库中还没有任何提交)或不明确(因为你创建了一个名为HEAD的分支,这是一件你不应该做的蠢事),则会失败。这一点在Git 1.8.2中有所改变,所以在现代版本的Git中,你甚至可以在做出第一次提交之前使用上述命令。

"git reset"(无选项或参数)用于在以下情况下出错 的时候会出错,但现在它会给你一个 一个空的索引(与不存在的提交相匹配,你甚至不在其中)。

评论(11)

你想。

git rm --cached 

推理。

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

git reset .

(撤销我最初的全部添加),却得到了这个(不是很有用的)信息。

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

原来,这是因为head ref(分支?)在第一次提交后才存在。 也就是说,如果你的工作流程和我一样,你会遇到和我一样的初学者问题。

  1. cd到我的新项目目录下,尝试一下 Git,新的热点。
  2. git init
  3. `git add .``
  4. git status

... 很多废话滚动的...

=> 妈的,我不想把这些都加进去。

  1. 谷歌"撤销git添加&quot。

=&gt。 找到Stack Overflow - 耶

  1. git reset .

=> fatal: Fatal: Failed to resolve 'HEAD' 作为一个有效的 ref。

进一步发现,在邮件列表中,有'的[bug记录][1]针对这个无益的问题。

而正确的解决方案就在Git状态输出中(是的,我把它当作'废话)。

... .gt;

有待承诺的改变。

(使用"git rm --cached ..."

来取消阶段) ...

解决办法确实是使用git rm --cached FILE

请注意其他地方的警告 - git rm会删除文件的本地工作副本,但如果你使用--缓存则不会。 这里是git help rm的结果。

--cached &gt.使用这个选项可以取消阶段,只从索引中删除路径。 使用该选项可以取消阶段,只从索引中删除路径。 使用此选项取消阶段,只从索引中删除路径。 工作树文件,无论是否修改,都会被留下。

我继续使用

git rm --cached .

来删除所有的东西并重新开始。 不过没能成功,因为虽然add .是递归的,但原来rm需要-r才能递归。 叹了口气。

git rm -r --cached .

好了,现在我'又回到了开始的地方。 下次我'要用-n来做一次干货,看看会增加什么。

git add -n .

在相信 "git help rm "关于"--缓存 "不会破坏任何东西之前,我把所有东西都压缩到了一个安全的地方(如果我拼错了怎么办)。

[1]: http://kerneltrap.org/mailarchive/git/2008/2/13/846664/thread

评论(23)

如果你输入

git status

Git 会告诉你什么是暂存,等等,包括如何解除暂存的说明。

use "git reset HEAD ..." to unstage

我发现在这种情况下,Git能很好地促使我做正确的事情。

注意:最近的Git版本(1.8.4.x)改变了这个信息:

(use "git rm --cached ..." to unstage)
评论(3)

澄清一下。 git add将当前工作目录中的更改移到staging区域(索引)。

这个过程叫做staging。 所以最自然的命令就是stage变化(修改的文件)。

git stage

git add只是git stage的一个更容易输入的别名。

可惜没有 "git unstage "或 "git unadd "命令。 相关的比较难猜或者说难记,但是很明显。

git reset HEAD --

我们可以很容易地为此创建一个别名。

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
评论(4)

除了公认的答案之外,如果你错误添加的文件很大,你可能会注意到,即使用'git reset'从索引中删除了它,它似乎仍然占据了.git目录的空间。

这没什么好担心的。 该文件确实还在版本库中,但只是作为一个"松散对象"。 它不会被复制到其他仓库(通过克隆、推送),空间最终会被回收--虽然可能不会很快。 如果你很着急,可以运行。

git gc --prune=now

更新 (以下是我试图澄清一些可能由最高票数的答案引起的混乱)。

那么,"git add "的真正*undo是什么?

git reset HEAD <file> ?

还是

git rm --cached <file>

严格来说,如果我没有弄错的话。 严格来说,如果我没记错的话,没有.

git add 不能撤销 - 安全地,一般来说。

让我们先回顾一下git add <file>的实际作用。

  1. 如果<file>之前没有被跟踪git add就会将其与当前内容一起添加到缓存中**。

  2. 如果<file>已经被跟踪git add 将当前内容(快照、版本)保存到缓存中。 在Git中,这个操作仍然叫做添加,(而不是单纯的更新),因为一个文件的两个不同版本(快照)被视为两个不同的项目。 因此,我们确实是在缓存中添加了一个新的项目,并将在以后提交。

有鉴于此,这个问题略显含糊。

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

OP'的情况似乎是第一种(未追踪的文件),我们希望用"undo" 从跟踪的项目中删除文件(不只是当前内容)。 如果是这种情况,那么运行git rm --cached <file>就可以了。

而且我们还可以运行git reset HEAD <file>。 一般来说,这是比较好的,因为它在两种情况下都能用。 当我们错误地添加了一个已经被跟踪的项目的版本时,它也会进行撤销。

但是有两个注意事项。

首先。 只有一种情况下(正如答案中所指出的),"git reset HEAD "不起作用,但 "git rm --cached "起作用。 一个新的版本库(没有提交)。 但实际上,这只是一个无关紧要的情况。

第二种情况。 要知道,git reset HEAD并不能神奇地恢复之前缓存的文件内容,它只是从HEAD重新同步。 如果我们误入歧途的git add覆盖了之前暂存的未提交的版本,我们就无法恢复。 这就是为什么严格来说,我们不能撤销[*]。

例如:{{{5439876}}。

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

使用Git可以很容易地撤销一个已经添加的文件。 要重置已经添加的myfile.txt,请使用。

git reset HEAD myfile.txt

解释:

当你暂存了不需要的文件后,要撤销,你可以执行git resetHead是你在本地的文件头,最后一个参数是你的文件名。

我在下图中为你创建了更详细的步骤,包括在这些情况下可能发生的所有步骤。

[![git reset HEAD file][1]][1]

[1]: https://i.stack.imgur.com/9JgGD.jpg

评论(2)
git rm --cached . -r

将"取消添加&quot。 从当前目录中递归添加的所有内容。

评论(3)

运转

git gui

并手动删除所有文件,或选择所有文件并点击取消提交按钮。

评论(4)

Git的命令涵盖了所有可以想象到的操作,但它需要大量的知识才能正确地进行操作,正因为如此,它最多也是反直觉的......

**你之前做了什么:***

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

你想要什么:

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

git reset head

  • 将文件从head重置到最后的状态,撤销修改并从索引中删除。

<!-- language: lang-bash -->

想想svn revert <file> IIRC。

git reset HEAD git checkout

如果你有一个<branch>的名字,比如<file>,就用。

git checkout -- <file&gt。

这是很有必要的,因为git reset --hard HEAD对单个文件不起作用。

  • 从索引和版本管理中删除<file>,保留未版本的文件和工作副本中的变化。

git rm --cached

  • 从工作副本和版本管理中完全删除<file>

git rm

评论(3)

这个问题没有明确提出来。 原因是git add有两层意思。

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

如果有疑问,使用

git reset HEAD file

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

警告:如果你对一个被**修改过的文件(一个之前存在于版本库中的文件)执行 "git rm --cached file",那么这个文件将在 "git commit "时被删除!它仍然存在于你的文件系统中,但如果其他人拉你的提交,这个文件将从他们的工作树中删除。 它仍然存在于你的文件系统中,但如果其他人拉你的提交,该文件将从他们的工作树中删除。

git status会告诉你这个文件是新文件还是修改

On branch master
Changes to be committed:
  (use "git reset HEAD ..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt
评论(2)

如果你正在进行首次提交,而你又不能使用git reset,只需声明"Git破产&quot。 并删除.git文件夹,然后重新开始。

评论(2)

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

但是:

我发现了这个很棒的小贴子,它实际上为 "git unadd "添加了Git命令(嗯,一个别名)。 详情请看[git unadd][2]

简单地说。

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

现在你可以

git unadd foo.txt bar.txt

[1]: https://www.kernel.org/pub/software/scm/git/docs/git-reset.html [2]: https://blog.pivotal.io/labs/labs/git-unadd

评论(0)

使用 "git add -i "从即将到来的提交中删除刚刚添加的文件。 例如

添加你不想要的文件。

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

进入交互式添加撤销你的添加(在git这里输入的命令是"r&quot。 (revert),"1" (revert列表中的第一个条目显示),'return&#39。 退出还原模式,以及"q&quot。 (退出)。

$ 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&quot。 又回到了未被追踪的列表中。

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

git removegit rm可用于此,使用--cached标志。试试吧。

git help rm
评论(2)

当你开始一个新的项目时,这里有一个方法可以避免这个令人烦恼的问题。

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

如果你没有任何提交,Git 会让你很难做git reset。 如果你只是为了有一个小的初始提交,那么之后你就可以随意地进行 "git add -A "和 "git reset",以使一切都正确。

这种方法的另一个好处是,如果你以后遇到行末问题,需要刷新所有文件,那很容易。

  • 签出那个初始提交。 这将会删除你所有的文件。
  • 然后再次检查你最近的提交。 这将使用你当前的换行设置,重新获取你的文件副本。
评论(4)

请注意,如果你没有指定修订版,那么你必须包含一个分隔符。 我的控制台中的例子。

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)

评论(1)

也许在你发布问题后,Git已经进化了。

$> git --version
git version 1.6.2.1

现在,你可以试试。

git reset HEAD .

这应该是你要找的。

评论(1)

要按照上面的建议,从暂存区中删除新文件(而且只在有新文件的情况下)。

git rm --cached FILE

只对意外添加的新文件使用rm -缓存。

评论(2)

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

git reset *
评论(2)

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

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

等等。

评论(1)