如何取消暂存大量文件而不删除内容


454

我不小心使用了许多临时文件 git add -A

我设法使用以下命令取消暂存文件,并设法删除脏索引。

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

以上命令在中列出git help rm。但是可悲的是,即使我指定了缓存选项,我的文件在执行时也会被删除。如何清除索引而不丢失内容?

如果有人可以解释此管道操作的方式,也将很有帮助。


8
rm -f不是git命令,没有--cached选项。在执行之前,您的本地文件已被删除,git rm因此我认为您不应该git rm为任何事情负责。
CB Bailey

8
@sarat,请考虑更改正确的答案,从高度upvoted答案伊恩·马多克斯,因为git reset --hard不正确的答案,将在事实上删除的内容。这会让用户感到困惑-就像我一样。
Marco Pashkov

2
正如Marco所说,@ sarat,继续。此页面的流量很大。
罗斯

@MarcoPashkov和Ross谢谢大家。做完了
萨拉特

Answers:


986

git reset

如果您只想撤消过度的“ git add”运行,请执行以下操作:

git reset

您所做的更改将撤消,可以随时根据需要重新添加。


请勿运行git reset --hard

它不仅会取消登台添加的文件,还将还原您在工作目录中所做的所有更改。如果您在工作目录中创建了任何新文件,则不会删除它们。


15
我欠你一品脱的伊恩
DasBooten

1
我经常发现自己也必须表现git checkout -- *出色
Den-Jason

1
您节省了很多精力。谢谢男人
RajnikantDixit,

35

如果你有一个原始的回购(或头未设置)[1]你可以简单地

rm .git/index

当然,这将要求您重新添加确实要添加的文件。


[1]注意(如注释中所述),通常仅在回购是全新的(“原始”)或未提交任何内容时才会发生。从技术上讲,每当没有结帐或工作树时。

只是让它更清楚:)


是的,这更像是删除创建的索引本身。好是,我不需要重新初始化git。谢谢!
萨拉特2011年

确定操作安全吗?我只是这样做(实际上将索引移开了),然后将所有其他文件上载以便删除。
辛格

@inger“如果您有原始存储库”。您显然没有。
sehe

其实,我想知道您所说的“原始回购”是什么意思(我对Google也不满意)。那么,您实际上是指一个空的回购吗?
辛格

1
@inger同意。我必须假设OP恰好有这种确切情况-他没有具体说明,但他的描述留有可能。无论如何,我只是在共享信息,不能影响投票:(。在回答文字中加了警告的字样,以防将来对其他人
有所

15

使用git reset HEAD不删除文件重置索引。(如果您只想重置索引中的特定文件,则可以git reset HEAD -- /path/to/file这样做。)

外壳中的管道操作员stdout从左侧获取流程的内容,然后将其传递stdin给右侧的流程。它基本上等同于:

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

但是,相反$ proc1 | proc2,第二个过程可以在第一个过程完成输出之前开始获取数据,并且不涉及任何实际文件。


但是如何将其与多个文件一起使用。我以前从未提交过这些文件。
2011年

3
只需键入git reset HEAD而不指定任何其他内容,它将重置整个索引。然后,您可以只重新添加所需的文件。
琥珀

我收到以下错误。我以前从未承诺过这些项目。 $ git reset HEAD fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
2011年

1
刚尝试git reset,不使用HEAD
琥珀

我已经尝试过结束以下错误。$ git reset fatal: Failed to resolve 'HEAD' as a valid ref.
2011年

9
git stash && git stash pop

2
我会做“ git stash && git stash pop”,这样就可以删除该stash。“应用”会将隐藏项保留在隐藏项列表中。
chitti

8

如果未设置HEAD(即,您尚未提交,但是您不想.git因为已经设置了要保留的其他存储库配置而被淘汰),您也可以执行

git rm -rf --cached .

放开一切。这实际上与sehe的解决方案相同,但避免了使用Git内部部件造成的混乱。


这实际上告诉Git删除缓存区域中的所有内容。
有远见的软件解决方案

1
缓存也称为暂存区域,因此我不确定您要获得什么。
jjlin

从sehe来看,rm .git / index是非常危险的-请务必阅读他关于全新回购协议的注意事项!对于其他99.999%的时间来说,这要安全得多。我没有仔细阅读,在对工作副本执行rm .git / index之后,不得不删除我的工作副本并重新克隆。
phpguru

不要使用此命令!它将所有项目更改为未跟踪状态(包括未上演的状态)。这不是原始问题的解决方案。使用'git rm'命令的正确解决方案是仅指定要取消暂存的文件:git rm -rf --cached <要取消暂存的文件>。
蒙特Creasor

您只有在拥有尚未提交的新存储库时才应使用此命令(这是“未设置HEAD”的意思),但是您不想.git因为安装了其他存储库配置而被吹嘘了。想要保持。我已经进行编辑以澄清这一点。
jjlin

5

警告:除非您要丢失未完成的工作,否则请不要使用以下命令!

使用git reset进行了说明,但你要的管道命令的解释一样,所以这里有云:

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

该命令git ls-files列出了git知道的所有文件。该选项-z在其上强加了一种特定的格式,,由预期,该格式xargs -0随后rm -f将对它们进行调用,这意味着在不检查您的批准的情况下将其删除。

换句话说,“列出git知道的所有文件并删除本地副本”。

然后进入git diff,显示git知道的不同版本的项目之间的变化。这些可以是不同树之间的更改,本地副本和远程副本之间的差异,等等。
如此处所用,它显示了未分阶段的更改;您已更改但尚未提交的文件。该选项--name-only意味着您只需要(完整)文件名,并且--diff-filter=D仅对删除的文件感兴趣。(嘿,我们不只是删除一堆东西吗?) 然后将其通过管道传递到xargs -0我们之前看到的代码中,从而对其进行调用git rm --cached,这意味着它们已从缓存中删除,而工作树应单独放置-除非如此您刚刚从工作树中删除了所有文件。现在它们也从您的索引中删除。

换句话说,所有已上演或未上演的更改均已消失,并且您的工作树为空。哭一声,从源或远程重新签出文件,然后重做您的工作。诅咒写这些地狱线的虐待狂;我完全不知道为什么有人要这么做。


TL; DR:您刚刚完成了所有工作;重新开始并git reset从现在开始使用。


2

恐怕这些命令行中的第一个无条件地从工作副本中删除了git暂存区中的所有文件。第二个文件取消转储已跟踪但已删除的所有文件。不幸的是,这意味着您将丢失对这些文件的所有未提交的修改。

如果要使工作副本和索引恢复到上一次提交时的状态,则可以(仔细地)使用以下命令:

git reset --hard

我说“小心”是因为git reset --hard 它将消除工作副本和索引中未提交的更改。但是,在这种情况下,听起来好像您只是想回到上一次提交时的状态,并且未提交的更改无论如何都已丢失。

更新:从您对Amber答案的评论中可以看出,您尚未创建任何提交(因为HEAD无法解析),所以这无济于事。

至于如何将这些管道的工作:git ls-files -zgit diff --name-only --diff-filter=D -z两个输出文件名列表分开与字节0。(这很有用,因为与换行符不同,0保证在类似Unix的系统上文件名中不会出现字节。)该程序xargs实质上是从标准输入中构建命令行,默认情况下是从标准输入中获取命令行并将其添加到末尾命令行。该-0选项说期望标准输入以0字节分隔。 xargs可能多次调用该命令以用尽标准输入中的所有参数,请确保命令行永远不会变得太长。

举一个简单的例子,如果您有一个名为的文件test.txt,其内容如下:

hello
goodbye
hello again

...然后该命令xargs echo whatever < test.txt将调用该命令:

echo whatever hello goodbye hello again

我从未提交过任何内容,因此它会说无法解决HEAD。在这种情况下我们该做什么。非常感谢您详细解释管道。
萨拉特2011年

8
如果您刚刚更改了git忽略并且做了git add --all以包括很多文件,请不要运行git reset --hard取消它们的暂存。他们将被删除!
2014年

5
啊啊!也许您需要突出显示“小心”一词。我刚刚看到这三个词“ git reset --hard”,我所有未暂存的文件都是... fufff!不见了!!!!!
Vineeth Chitteti 2014年

1

如果您想撤消所有更改,请使用以下命令,

git reset --soft HEAD

如果您要取消更改并从工作目录还原它们,

git reset --hard HEAD
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.