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

问题描述 投票:8123回答:34

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

git add myfile.txt

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

git version-control git-commit git-stage
34个回答
9349
投票

您可以在提交之前撤消git add

git reset <file>

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

您可以使用

git reset

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

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

当您在历史记录中没有任何提交时,“git reset”(没有选项或参数)用于错误输出,但它现在为您提供一个空索引(以匹配您不存在的不存在的提交)。


73
投票

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

  1. 将新文件添加到暂存区域,然后使用git rm --cached file撤消。
  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 <file>..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt

63
投票

如果您正在进行初始提交并且无法使用git reset,只需声明“Git破产”并删除.git文件夹并重新开始


55
投票

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

但:

我发现这个伟大的小帖子实际上为git unadd添加了Git命令(以及别名):有关详细信息,请参阅git unadd或..

只是,

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

现在你可以

git unadd foo.txt bar.txt

44
投票

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

git help rm

42
投票

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

进入交互式添加以撤消你的添加(在这里输入的命令是“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.
$

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

37
投票

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

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

如果您没有任何提交,Git会让git reset变得非常困难。如果你创建一个微小的初始提交只是为了拥有一个,之后你可以根据需要多次git add -Agit reset,以使一切正确。

这种方法的另一个优点是,如果您以后遇到线路结束的问题并需要刷新所有文件,这很容易:

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

33
投票

也许自你发布问题以来Git已经发展了。

$> git --version
git version 1.6.2.1

现在,您可以尝试:

git reset HEAD .

这应该是你正在寻找的。


33
投票

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

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)


30
投票

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

git rm --cached FILE

仅将rm --cached用于意外添加的新文件。


24
投票

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

git reset *

2066
投票

你要:

git rm --cached <added_file_to_undo>

推理:

当我刚接触这个时,我首先尝试过

git reset .

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

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

事实证明这是因为HEAD ref(branch?)直到第一次提交之后才存在。也就是说,如果你的工作流程像我一样,你会遇到和我一样的初学者问题:

  1. cd到我伟大的新项目目录,尝试Git,新的热点
  2. git init
  3. git add .
  4. git status ......很多废话卷轴...... =>该死,我不想加上所有这些。
  5. 谷歌“撤消git添加” =>找到Stack Overflow - yay
  6. git reset . =>致命:无法将'HEAD'解析为有效的参考号。

事实证明,a bug logged反对邮件列表中的这个无益。

并且正确的解决方案就在Git状态输出中(是的,我把它作为'废话'掩盖了)

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

而解决方案确实是使用git rm --cached FILE

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

--cached使用此选项仅从索引中取消暂存和删除路径。将保留工作树文件,无论是否已修改。

我继续使用

git rm --cached .

删除所有内容并重新开始。虽然没有工作,因为虽然add .是递归的,但结果rm需要-r来递减。叹。

git rm -r --cached .

好的,现在我回到了我开始的地方。下次我要使用-n进行干运行,看看会添加什么:

git add -n .

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


24
投票

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

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

等等


22
投票

只需键入git reset它就会恢复,就像你上次提交时从未输入git add .一样。确保你以前犯过。


18
投票

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

enter image description here

假设我意外地添加了文件,git add newFile.txt

enter image description here

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

enter image description here


17
投票

对于特定文件:

  • git reset my_file.txt
  • git checkout my_file.txt

对于所有添加的文件:

  • git重置。
  • git checkout。

注意:checkout更改文件中的代码并移至上次更新(已提交)状态。重置不会改变代码;它只是重置标题。


13
投票

此命令将取消暂停您的更改:

git reset HEAD filename.txt

你也可以使用

git add -p 

添加部分文件。


13
投票

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

git add -i

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

要选择一个序列,只需输入1-5即可从1到5。

Git staging files


13
投票

要撤消git add use

git reset filename


9
投票
git reset filename.txt

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


9
投票

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

与此命令完全相反的是,

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

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

它将使用指定的文件重置您的头部。所以,如果你的头没有它的意思,它只会重置它


8
投票

在SourceTree中,您可以通过gui轻松完成此操作。您可以检查sourcetree用于取消暂存文件的命令。

我创建了一个新文件并将其添加到git中。然后我使用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来取消暂存新文件。


509
投票

如果输入:

git status

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

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

我发现git在推动我在这样的情况下做正确的事情方面做得非常好。

注意:最近的git版本(1.8.4.x)已更改此消息:

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

7
投票

最直观的解决方案之一是使用SourceTree

您只需从暂存和未分阶段的enter image description here拖放文件即可


240
投票

为了澄清:git add将更改从当前工作目录移动到暂存区域(索引)。

此过程称为分段。所以,最自然的命令来进行更改(更改文件)是显而易见的:

git stage

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

可惜没有git unstagegit 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

161
投票

对于已接受的答案的补充,如果您错误添加的文件很大,您可能会注意到,即使在使用'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中,这个动作仍称为add,(不仅仅是更新它),因为文件的两个不同版本(快照)被视为两个不同的项目:因此,我们确实在缓存中添加了一个新项目,最终稍后提交。

鉴于此,问题有点含糊:

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

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 lost irrevocably "version 2"
-version 1
+version 3

当然,如果我们只是按照通常的懒惰工作流程来执行'git add'仅用于添加新文件(案例1),并且我们通过commit,git commit -a命令更新新内容,这不是非常关键。


*(编辑:以上几乎是正确的,但仍然可以有一些稍微讨厌/错综复杂的方法来恢复已上演但未提交然后被覆盖的更改 - 请参阅Johannes Matokic和iolsmit的评论)


92
投票
git rm --cached . -r

将以递归方式“取消添加”您从当前目录添加的所有内容


88
投票

使用git撤消已添加的文件很容易,重置已添加的myfile.txt,使用:

git reset HEAD myfile.txt

说明:

在您上传不需要的文件后,要撤消,您可以执行git resetHead是本地文件的头部,最后一个参数是文件的名称。

我将在下面的图片中为您创建更多详细信息,包括在这些情况下可能发生的所有步骤:

git reset HEAD file


86
投票

git gui

并手动删除所有文件或选择所有文件,然后单击“提交”按钮。


80
投票

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>
© www.soinside.com 2019 - 2024. All rights reserved.