如何在不删除内容的情况下取消大量的文件

我不小心使用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中列出。 但不幸的是,我的文件也被删除执行,即使我已经给了caching选项。 如何清除索引而不丢失内容?

如果有人可以解释这种pipe道操作的方式,这也是有帮助的。

git reset

如果你想要的只是撤销一个过度热闹的“git add”运行:

 git reset 

您的更改将被取消,随时可以重新添加。


不要运行git reset --hard

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

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

 rm .git/index 

当然,这将需要您重新添加您想添加的文件。


注意(正如评论中所解释的),这通常只会在回购是全新的(“原始”)或者没有提交时才会发生。 更技术性地说,只要没有结账或工作树。

Jus使它更清楚:)

使用git reset HEAD重置索引而不删除文件。 (如果你只想重置索引中的特定文件,可以使用git reset HEAD -- /path/to/file来完成。)

pipe道操作员在一个shell中,将进程的stdout放在左边,并将其作为stdin传递给右边的进程。 它基本上相当于:

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

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

如果HEAD没有设置,你也可以这样做

 git rm -rf --cached . 

停止一切。 这和sehe的解决scheme实际上是一样的,但是避免使用Git内部。

 git stash && git stash pop 

警告:不要使用下面的命令,除非你想失去未提交的工作!

已经解释了使用git reset ,但是您也要求对pipe道命令进行解释,所以这里是:

 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意味着您--name-only需要(完整)文件名,而--diff-filter=D意味着您只对已删除的文件感兴趣。 (嘿,我们不是刚刚删除了一堆东西吗?)然后它被传入我们之前看到的xargs -0 ,它调用了git rm --cached对它们进行了caching,这意味着它们从caching中被移除,而工作树应该被单独留下 – 除了你刚刚从工作树中删除所有文件。 现在他们也从您的索引中删除。

换句话说,上演或未上架的所有变化都消失了,你的工作树是空的。 哭了起来,从原始或远程检查您的文件,并重做您的工作。 诅咒写下这些恶行的虐待者; 我不知道为什么有人会想这样做。


TL; DR:你刚刚把一切都弄清楚了; 从现在开始git reset使用git reset

恐怕这些命令行中的第一个无条件地从工作副本中删除了所有在git临时区域中的文件。 第二个分离所有被跟踪的文件,但现在已经被删除。 不幸的是,这意味着你将失去对这些文件的任何未提交的修改。

如果你想让你的工作副本和索引返回到最后一次提交的方式 ,你可以( 仔细地 )使用下面的命令:

 git reset --hard 

我从git reset --hard “仔细地”说出git reset --hard 将会消除你的工作副本和索引中未经改变的变化 。 但是,在这种情况下,听起来好像你只是想回到最后一次提交时的状态,而未提交的更改已经丢失了。

更新:这听起来来自你对Amber的回答的评论,你还没有创build任何提交(因为HEAD无法parsing),所以这恐怕没有帮助。

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

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

 hello goodbye hello again 

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

 echo whatever hello goodbye hello again 

如果你想取消所有的改变使用下面的命令,

 git reset --soft HEAD 

如果您想要暂停更改并从工作目录中恢复它们,

 git reset --hard HEAD