首页 文章

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

提问于
浏览
366

我不小心使用 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 回答

  • 14

    git重置

    如果你想要的是撤消一个过于热心的“git add”运行:

    git reset
    

    您的更改将无法进行,并随时可以重新添加 .


    DO NOT RUN git reset --hard.

    它不仅会取消暂存您添加的文件,还会还原您在工作目录中所做的任何更改 . 如果您在工作目录中创建了任何新文件,则 will not 会删除它们 .

  • 1

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

    rm .git/index
    

    当然,这将要求您重新添加您想要添加的文件 .


    [1] 注意(如评论中所述)这通常只会在回购是全新的("pristine")或者没有提交时才会发生 . 更技术上,只要没有结账或工作树 .

    只是让它更清楚:)

  • 33

    使用 git reset HEAD 重置索引而不删除文件 . (如果您只想重置索引中的特定文件,可以使用 git reset HEAD -- /path/to/file 来执行此操作 . )

    shell中的管道运算符在左侧获取进程的 stdout ,并将其作为 stdin 传递给右侧的进程 . 它基本上相当于:

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

    但是它是 $ proc1 | proc2 ,第二个进程可以在第一个进程输出数据之前开始获取数据,并且没有涉及的实际文件 .

  • 9

    如果未设置HEAD,您也可以这样做

    git rm -rf --cached .
    

    展开一切 . 这实际上与sehe的解决方案相同,但避免与Git内部结合 .

  • 5
    git stash && git stash pop
    
  • 8

    Warning: do not use the following command unless you want to lose uncommitted work!

    已经解释了使用 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 ,这意味着它们会从缓存中删除,而工作树应该保持独立 - 除了你've just removed all files from your working tree. Now they'也从你的索引中删除 .

    换句话说,所有已暂存或未暂存的更改都将消失,并且您的工作树为空 . 哭泣,从原产地或远程检查你的文件,并重做你的工作 . 诅咒写下这些地狱线的虐待狂;我不知道为什么有人想要这样做 .


    TL;DR: you just hosed everything; start over and use git reset from now on.

  • 1

    我担心这些命令行中的第一个无条件地从工作副本中删除了git的临时区域中的所有文件 . 第二个未分阶段已跟踪但已被删除的所有文件 . 不幸的是,这意味着您将丢失对这些文件的任何未提交的修改 .

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

    git reset --hard
    

    我说"carefully"自 git reset --hard will obliterate uncommitted changes in your working copy 和索引 . 但是,在这种情况下,听起来好像您只是想在上一次提交时返回状态,并且无论如何都未丢失未提交的更改 .

    更新:它听起来你对Amber 's answer that you haven' t的评论但是创建了任何提交(因为HEAD无法解析),所以这让我害怕了.1108365_恐怕 .

    至于这些管道是如何工作的: 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
    
  • 804

    如果要使用以下命令取消暂存所有更改,

    git reset --soft HEAD
    

    如果您要取消暂停更改并将其从工作目录还原,

    git reset --hard HEAD
    

相关问题