我错误地使用以下命令将文件添加到 Git:
git add myfile.txt
我还没跑git commit
。有没有办法撤消这个,所以这些文件不会包含在提交中?
我错误地使用以下命令将文件添加到 Git:
git add myfile.txt
我还没跑git commit
。有没有办法撤消这个,所以这些文件不会包含在提交中?
git add
您可以在提交之前撤消
git reset <file>
这将从当前索引(“即将提交”列表)中删除它而不更改任何其他内容。
您可以使用
git reset
没有任何文件名来取消所有应有的更改。当有太多文件需要在合理的时间内一一列出时,这会派上用场。
在旧版本的 Git 中,上述命令分别相当于git reset HEAD <file>
和,如果未定义(因为您尚未在存储库中进行任何提交)或模棱两可(因为您创建了一个名为 的分支,这是一件愚蠢的事情git reset HEAD
,则将失败你不应该这样做)。不过,这在 Git 1.8.2 中有所更改,因此在现代版本的 Git 中,您甚至可以在首次提交之前使用上述命令:HEAD
HEAD
“git reset”(不带选项或参数)用于在您的历史记录中没有任何提交时出错,但现在它为您提供一个空索引(以匹配您甚至不存在的不存在的提交)。
文档:git reset
你要:
git rm --cached <added_file_to_undo>
推理:
当我是新手时,我第一次尝试
git reset .
(撤消我的整个初始添加),只是为了得到这个(不是那么)有用的信息:
fatal: Failed to resolve 'HEAD' as a valid ref.
事实证明,这是因为 HEAD ref(分支?)直到第一次提交之后才存在。也就是说,如果你的工作流程和我一样,你会遇到和我一样的初学者问题:
git init
git add .
git status
...很多废话卷轴...
=>该死的,我不想添加所有这些。
谷歌“撤消 git 添加”
=> 找到堆栈溢出 - 耶
git reset .
=> 致命:无法将“HEAD”解析为有效参考。
进一步证明,在邮件列表中记录了一个针对此无用的错误。
并且正确的解决方案就在 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 .
删除所有内容并重新开始。但是没有用,因为 whileadd .
是递归的,结果rm
需要-r
递归。叹。
git rm -r --cached .
好的,现在我回到我开始的地方。下次我打算用-n
做一个dry run,看看会添加什么:
git add -n .
git help rm
在相信不会破坏任何东西之前,我把所有东西都拉到了安全的地方--cached
(如果我拼错了怎么办)。
如果您键入:
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
将更改从当前工作目录移动到暂存区(索引)。
这个过程称为staging。因此,用于暂存更改(更改的文件)的最自然命令是显而易见的命令:
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
除了接受的答案之外,如果您错误添加的文件很大,您可能会注意到,即使在使用 ' git reset
' 从索引中删除它之后,它似乎仍然占用.git
目录中的空间。
这没什么好担心的;该文件确实仍在存储库中,但仅作为“松散对象”。它不会被复制到其他存储库(通过克隆、推送),并且空间最终会被回收——尽管可能不会很快。如果你着急,你可以运行:
git gc --prune=now
更新(以下是我试图消除最受好评的答案可能引起的一些混淆):
那么,真正的撤销是git add
什么?
git reset HEAD <file>
?
或者
git rm --cached <file>
?
严格来说,如果我没记错的话:none。
git add
无法撤消- 通常是安全的。
让我们首先回顾一下git add <file>
实际做了什么:
如果<file>
之前没有跟踪,git add
则将其添加到缓存中,并带有其当前内容。
如果已经<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 irrevocably lost "version 2"
-version 1
+version 3
当然,如果我们只是遵循通常的惰性工作流程,只为添加新文件(案例 1)执行“git add”,并且我们通过 commitgit commit -a
命令更新新内容,这并不是很关键。
*(编辑:以上内容实际上是正确的,但仍然有一些稍微有点骇人听闻/令人费解的方法来恢复已暂存但未提交然后被覆盖的更改 - 请参阅 Johannes Matokic 和 iolsmit 的评论)
git rm --cached . -r
将以递归方式“取消添加”您从当前目录中添加的所有内容
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 gui
并手动删除所有文件,或者选择所有文件并单击unstage from commit按钮。
问题没有明确提出。原因在于它git add
有两层含义:
git rm --cached file
.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
根据许多其他答案,您可以使用git reset
但:
我发现这篇很棒的小帖子实际上为以下内容添加了 Git 命令(嗯,一个别名)git unadd
:有关详细信息,请参阅git unadd或..
简单地,
git config --global alias.unadd "reset HEAD"
现在你可以
git unadd foo.txt bar.txt
或者/直接:
git reset HEAD foo.txt bar.txt
如果您处于初始提交并且无法使用git reset
,只需声明“Git 破产”并删除.git
文件夹并重新开始
git reset filename.txt
将从当前索引中删除一个命名的文件filename.txt
(也称为“暂存区”,这是保存“即将提交”的更改的地方),而不更改任何其他内容(工作目录不会被覆盖)。
用于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”(还原)、“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)
$
当你开始一个新项目时,这里有一种方法可以避免这个令人烦恼的问题:
git init
。git reset
如果你没有任何提交,Git 会让你很难做到。如果您创建一个很小的初始提交只是为了拥有一个,那么您可以在此之后git add -A
尽可能git reset
多地进行操作,以使所有事情都正确。
这种方法的另一个优点是,如果您以后遇到行尾问题并需要刷新所有文件,这很容易:
请注意,如果您未能指定修订,则必须包含分隔符。我的控制台中的示例:
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)
自从您发布问题以来,也许 Git 已经进化了。
$> git --version
git version 1.6.2.1
现在,您可以尝试:
git reset HEAD .
这应该是您正在寻找的。
正如其他人在相关问题中指出的那样(请参阅此处、此处、此处、此处、此处、此处和此处),您现在可以使用以下命令取消暂存单个文件:
git restore --staged <file>
并取消暂存所有文件(从 repo 的根目录):
git restore --staged .
git restore
于2019 年 7 月推出,并在 2.23 版本中发布。
使用--staged
标志,它恢复索引的内容(这里问的是什么)。
当git status
使用暂存的未提交文件运行时,这是 Git 建议用来取消暂存文件的方法(而不是git reset HEAD <file>
以前 v2.23 之前的做法)。
要从暂存区域中删除新文件(并且仅在新文件的情况下),如上所述:
git rm --cached FILE
仅对意外添加的新文件使用 rm --cached。
要重置特定文件夹(及其子文件夹)中的每个文件,可以使用以下命令:
git reset *
使用*
命令一次处理多个文件:
git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*
等等
只需键入git reset
它就会恢复,就像您git add .
自上次提交以来从未键入过一样。确保你之前已经承诺过。
对于特定文件:
- git 重置 my_file.txt
- git checkout my_file.txt
对于所有添加的文件:
- 混帐重置。
- 混帐结帐。
注意:checkout更改文件中的代码并移动到最后更新(提交)状态。重置不会更改代码;它只是重置标题。
要撤消git add
,请使用:
git reset filename
还有交互模式:
git add -i
选择选项 3 取消添加文件。在我的情况下,我经常想要添加多个文件,并且在交互模式下,您可以使用这样的数字来添加文件。这将占用除 4 之外的所有内容:1、2、3 和 5
要选择一个序列,只需键入 1-5 即可从 1 到 5 全部取值。
此命令将取消隐藏您的更改:
git reset HEAD filename.txt
你也可以使用
git add -p
添加部分文件。
git add myfile.txt
# 这会将您的文件添加到待提交列表中
与此命令完全相反的是,
git reset HEAD myfile.txt # This will undo it.
因此,您将处于以前的状态。指定将再次处于未跟踪列表中(以前的状态)。
它将使用该指定文件重置您的头部。所以,如果你的脑袋没有它的意思,它会简单地重置它。
git reset filename.txt
将从当前索引中删除名为 filename.txt 的文件,即“即将提交”区域,而不更改任何其他内容。
在 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
新文件。
您可以使用 git 命令或 GUI git 取消暂存/撤消。
单个文件
git reset File.txt
多个文件
git reset File1.txt File2.txt File3.txt
示例- 假设您错误地添加了Home.js 、 ListItem.js 、 Update.js并且 想要撤消/重置 =>
git reset src/components/home/Home.js src/components/listItem/ListItem.js src/components/update/Update.js
使用git GUI的相同示例
git gui
该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
. 它只是不需要文件或路径即可工作。
您可以--soft
使用git reset
. 它将存储库重置为您指定的提交并暂存所有这些更改。您已经暂存的任何更改都不会受到影响,工作树中的更改也不会受到影响。
最后,您可以使用它--mixed
来重置工作树,而无需暂存任何更改。这也会取消暂存的任何更改。
您可以在 git 版本 2.23 之后使用此命令:
git restore --staged <filename>
或者,您可以使用以下命令:
git reset HEAD <filename>
我会使用git restore --staged .
或git restore --staged <filename>
您也可以使用git rm --cached
,但是,该git rm
命令应该理想地用于已跟踪的文件。
如果您想恢复最后一次提交,但仍想将提交中所做的更改保留在本地,请使用以下命令:
git reset HEAD~1 --mixed
我第一次遇到这个问题时,我在这里找到了这篇文章,从第一个答案中我了解到我应该这样做git reset <filename>
。它工作得很好。
最后,我碰巧在我的主 git 文件夹中有几个子文件夹。git add .
我发现将所有文件添加到子文件夹中很容易,然后git reset
添加我不想添加的几个文件。
现在我有很多文件和子文件夹。一个接一个很乏味,git reset
但首先还是更容易git add .
,然后重置几个重/不需要但有用的文件和文件夹。
我发现下面的方法(这里或这里没有记录)相对容易。我希望它会有所帮助:
假设您有以下情况:
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
列表不断增长......
首先,制作/创建 abash shell script
并为其命名。说,git_add.sh
:
然后将所有路径添加到您想要在git reset
前面添加的所有文件夹和文件git 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
很重要。然后source git_add.sh
运行它。之后,你可以做git commit -m "some comment"
,然后git push -u origin master
如果你已经设置了 Bitbucket/Github。
免责声明:我只在 Linux 中测试过这个。
如果你有很多文件和文件夹总是保留在本地 git 存储库中,但你不希望 git 在你这样做时跟踪更改git add .
,比如视频和数据文件,你必须学习如何使用.gitignore
. 也许从这里。