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

时间:2008-12-07 21:57:47

标签: git version-control git-commit git-stage

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

git add myfile.txt

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


  

到目前为止有48个答案(有些已删除)。除非您有一些新信息,否则请不要添加新的。

41 个答案:

答案 0 :(得分:9233)

您可以在提交

之前撤消git add
git reset <file>

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

您可以使用

git reset

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

在旧版本的Git中,上述命令分别等同于git reset HEAD <file>git reset HEAD,如果HEAD未定义,则会失败(因为您尚未提交任何提交)你的回购)或模棱两可(因为你创建了一个名为HEAD的分支,这是一个你不应该做的愚蠢的事情)。这个was changed in Git 1.8.2,所以在现代版本的Git中,你甚至可以在第一次提交之前使用上面的命令:

  

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

答案 1 :(得分:2049)

你想:

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

    ......很多废话卷轴......

    =&GT;该死的,我不想加上所有这些。

  5. google“undo git add”

    =&GT;找到Stack Overflow - yay

  6. git reset .

    =&GT;致命:无法将“HEAD”解析为有效参考。

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

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

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

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

    请注意此处其他位置的警告 - git rm会删除文件的本地工作副本,但如果您使用 - 缓存,则不会。这是git help rm

    的结果
      

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

    我继续使用

    git rm --cached .
    

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

    git rm -r --cached .
    

    好的,现在我回到了我开始的地方。下次我将使用-n进行干运行并查看将要添加的内容:

    git add -n .
    

    我将所有内容压缩到一个安全的地方,然后相信git help rm关于--cached没有破坏任何东西(以及如果我拼错了它)。

答案 2 :(得分:507)

如果输入:

git status

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

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

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

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

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

答案 3 :(得分:238)

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

此过程称为 staging 。因此,阶段更改(更改文件)的最自然的命令是显而易见的:

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

答案 4 :(得分:160)

对于已接受的答案的补充,如果您错误添加的文件很大,您可能会注意到,即使在使用“git reset”将其从索引中删除后,它仍然会占用{ {1}}目录。这没有什么可担心的,文件确实仍在存储库中,但只是作为“松散对象”,它不会被复制到其他存储库(通过克隆,推送),并且空间最终将被回收 - 尽管也许不是很快。如果您感到焦虑,可以运行:

.git

更新(以下是我试图澄清最多投票答案可能引起的混淆):

那么,git gc --prune=now 的真正撤消是什么?

git add

git reset HEAD <file>

严格地说,如果我没弄错的话: none

git rm --cached <file> 无法撤消 - 一般情况下安全。

让我们先回想一下git add实际做了什么:

  1. 如果git add <file> 之前没有跟踪,则<file> 会将其添加到缓存及其当前内容。

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

  3. 鉴于此,问题有点含糊不清:

      

    我错误地使用命令...

    添加了文件

    OP的场景似乎是第一个(未跟踪文件),我们希望“撤消”从被跟踪的项目中删除文件(而不仅仅是当前内容)。 如果这种情况,则可以运行git add

    我们也可以运行git rm --cached <file>。这通常是可取的,因为它适用于两种情况:当我们错误地添加已经跟踪的项目的版本时,它也会进行撤消。

    但有两点需要注意。

    首先:(如答案中所指出的)只有git reset HEAD <file>不起作用但git reset HEAD不起作用的一种情况:新的存储库(没有提交)。但是,实际上,这是一个几乎无关紧要的案例。

    第二:请注意git rm --cached无法神奇地恢复以前缓存的文件内容,它只是从HEAD重新同步它。如果我们误入歧途的git reset HEAD覆盖了以前暂存的未提交版本,我们就无法恢复它。这就是为什么,严格来说,我们无法撤消[*]。

    示例:

    git add

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


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

答案 5 :(得分:91)

git rm --cached . -r

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

答案 6 :(得分:85)

运行

git gui

并手动删除所有文件,或者选择所有文件并单击 unstage from commit 按钮。

答案 7 :(得分:82)

使用 git

撤消已添加的文件非常简单,要重置已添加的myfile.txt,请使用:

git reset HEAD myfile.txt

<强>说明:

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

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

git reset HEAD file

答案 8 :(得分: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>
    

答案 9 :(得分:72)

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

  1. 新文件添加到暂存区域,然后使用git rm --cached file撤消。
  2. 已修改的文件添加到暂存区域,然后使用git reset HEAD file撤消。
  3. 如果有疑问,请使用

    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
    

答案 10 :(得分:62)

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

答案 11 :(得分:55)

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

<强> BUT:

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

简单地说,

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

现在你可以

git unadd foo.txt bar.txt

答案 12 :(得分:46)

git removegit rm可以使用--cached标记。尝试:

git help rm

答案 13 :(得分: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)
$

答案 14 :(得分:37)

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

  • 为新项目创建主目录。
  • 运行git init
  • 现在创建一个.gitignore文件(即使它是空的)。
  • 提交.gitignore文件。
如果你没有任何提交,Git会很难做git reset。如果你创建一个微小的初始提交只是为了拥有一个,那么你可以git add -Agit reset多次,以便让一切正常。

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

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

答案 15 :(得分:33)

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

$> git --version
git version 1.6.2.1

现在,您可以尝试:

git reset HEAD .

这应该是你要找的。

答案 16 :(得分: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)

答案 17 :(得分:30)

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

git rm --cached FILE

仅对意外添加的新文件使用rm --cached。

答案 18 :(得分:24)

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

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

答案 19 :(得分:24)

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

git reset *

答案 20 :(得分:22)

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

答案 21 :(得分:18)

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

enter image description here

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

enter image description here

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

enter image description here

答案 22 :(得分:17)

对于特定文件:

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

对于所有添加的文件:

  
      
  • git reset。
  •   
  • git checkout。
  •   

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

答案 23 :(得分:13)

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

git add -i

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

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

Git staging files

答案 24 :(得分:13)

撤消git add use

git reset filename

答案 25 :(得分:13)

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

git reset HEAD filename.txt

您也可以使用

git add -p 

添加部分文件。

答案 26 :(得分:9)

git reset filename.txt

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

答案 27 :(得分:9)

private void DirectoryItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (object item in e.NewItems) { (item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(Item_PropertyChanged); } } if (e.OldItems != null) { foreach (object item in e.OldItems) { (item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(Item_PropertyChanged); } } } #这会将您的文件添加到提交列表

与此命令完全相反的是,

git add myfile.txt

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

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

答案 28 :(得分: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来取消暂存新文件。

答案 29 :(得分:7)

git reset filename.txt  
  

将从当前索引中删除名为filename.txt的文件,&#34;即将提交&#34;区域,没有改变任何其他东西。

答案 30 :(得分:7)

2019更新

其他人指出,hereherehereherehereherehere ,您现在可以使用git restore --staged <file>进行此操作。

git restoreJuly 2019中引入,并在Git的2.23版本中发布。借助--staged标志,它可以还原索引的内容(此处要求的内容)。

在对暂存的未提交文件运行git status时,Git现在建议使用git restore --staged <file>进行暂存(而不是v2.23之前的git reset HEAD <file>)。 / p>

因此,为了取消暂存一个文件,您现在可以运行:

git restore --staged <file>

要取消暂存所有文件,可以从项目的根目录运行:

git restore --staged .

答案 31 :(得分:7)

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

您只需从暂存和未暂存中拖放文件即可 enter image description here

答案 32 :(得分:3)

您可以使用git命令或GUI git取消登台/撤消操作。

单个文件

git reset File.txt 

多个文件

git reset File1.txt File2.txt File3.txt

示例- 假设您误加了 Home.js ListItem.js Update.js enter image description here 并想要撤消/重置=>

git reset src/components/home/Home.js src/components/listItem/ListItem.js src/components/update/Update.js

enter image description here

使用 git GUI

的相同示例
git gui

打开一个窗口=>取消选中分段更改(将提交)中的文件 enter image description here

答案 33 :(得分:1)

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 HEADgit checkout HEAD的作用相同。它只是不需要文件或路径即可工作。

您可以将--softgit reset一起使用。它将存储库重置为您指定的提交,并逐步执行所有这些更改。您已经进行的任何更改都不会受到影响,工作树中的更改也不会受到影响。

最后,您可以使用--mixed重置工作树,而无需进行任何更改。这也会取消所有已暂存的更改。

答案 34 :(得分:0)

只需删除./git文件夹并从头开始。

答案 35 :(得分:0)

我第一次遇到此问题时,在这里找到了this post,从第一个答案中我得知我应该做git reset <filename>。效果很好。

最终,我在主git文件夹中碰巧有几个子文件夹。我发现只需执行git add .即可将所有文件添加到子文件夹中,然后git reset即可添加一些我不想添加的文件。

如今,我有很多文件和子文件夹。 git reset一步一步地工作很麻烦,但首先git add .仍然很容易,然后重设一些笨重/不需要但有用的文件和文件夹。

我发现以下方法(herehere未记录)相对容易。希望对您有所帮助:

假设您有以下情况:

Folder/SubFolder1/file1.txt
Folder/SubFolder2/fig1.png
Folder/SubFolderX/fig.svg
Folder/SubFolder3/<manyfiles>
Folder/SubFolder4/<file1.py, file2.py, ..., file60.py, ...>

您要添加所有文件夹和文件,但不添加fig1.png,而不添加SubFolderX,也不添加file60.py,并且列表不断增加...

首先,制作/创建一个bash shell script并为其命名。说git_add.sh

然后将所有路径添加到要git resetgit reset -- 之前的所有文件夹和文件中。随着文件列表的增加,您可以轻松地将路径复制粘贴到脚本git_add.sh中。 git_add.sh脚本应如下所示:

#!/bin/bash

git add .
git reset -- Folder/SubFolder2/fig1.png
git reset -- Folder/SubFolderX
git reset -- Folder/SubFolder4/file60.py

#!/bin/bash很重要。之后,您需要在命令行中执行chmod -x git_add.sh 使脚本可执行,然后source git_add.sh来运行它。之后,您可以先进行git commit -m "some comment",然后再进行git push -u origin master,如果您已经设置了Bitbucket / Github。

免责声明:我仅在Linux上对此进行过测试。

答案 36 :(得分:0)

使用 git reset HEAD 取消登台的所有内容

答案 37 :(得分:0)

您可以在git版本2.23之后使用此命令:

git restore --staged <filename>

或者,您可以使用以下命令:

git reset HEAD <filename>

答案 38 :(得分:0)

从原点转到您的功能分支

git checkout HEAD <file>

答案 39 :(得分:-5)

git stash && git stash pop

将会进行分期。

答案 40 :(得分:-9)

命令git reset --hard HEAD应该有效。需要注意的一点是,您需要将目录(cd)更改回正常的工作目录。否则,如果您从目录中运行命令,那么您错误地执行了git add . ....您将无法恢复,而是获得其他帖子中提到的错误“未知版本或路径不在工作树中”