【问题标题】:git rm * doesn't remove all files in one gogit rm * 不会一次性删除所有文件
【发布时间】:2013-10-14 15:31:20
【问题描述】:

我在尝试 git 的一些示例指令时遇到了这种特殊情况,即当我们执行 git rm * 时,它不会在第一次尝试时删除 .* 文件。 为什么会这样?

mkdir -p test_repo1/folder && cd test_repo1
touch .testfile1 .testfile2 testfile3 folder/testfile4 folder/.testfile5
git init && git add . && git commit -m "test commit"

如果现在我按如下方式执行git rm,我必须再次执行以删除所有文件

$ git rm -r *
rm 'folder/.testfile5'
rm 'folder/testfile4'
rm 'testfile3'

$ git rm -r *
rm '.testfile1'
rm '.testfile2'

为什么 git 在第一次尝试时不删除所有文件?另外,为什么只有 repo root 的文件会发生这种情况?

有趣的是,如果我只有那些 .testfiles,那么 git 会在第一次尝试时将它们删除。

我使用的是git版本1.7.9.5

【问题讨论】:

  • * 将被你的 shell 解释,检查它的通配规则
  • control x 会扩展 * 以便你看到它
  • 没有一个答案提到解决方案:如果您希望 * 被 git 解释,您需要引用或转义它:git rm -r '*'

标签: git


【解决方案1】:

通配符由您的 shell 扩展,默认情况下,在大多数 shell 中扩展不包括点文件。

所以到git执行的时候,第一个命令就变成了

git rm -r folder testfile3

第二个可能是文字

git rm -r *

其中git 然后自行扩展。

作为remarked by Keith, 一次性删除所有内容,防止shell 扩展通配符,以便git 第一次进行扩展。这可以使用双引号或单引号来完成,或者在星号前使用反斜杠。我更喜欢单引号:

git rm -r '*'

【讨论】:

    【解决方案2】:

    Shell 通配符

    当您运行git rm * 时,您实际上是在使用shell 的通配规则将参数传递给git-rm(1)。默认情况下,许多 shell 不包含隐藏文件(例如带有前导点的文件)。在 Bash 中,您可以使用 dotglobGLOBIGNORE 更改通配规则。例如:

    • 使用 shopt 内置:

      # set dotglob
      shopt -s dotglob
      
      git rm *
      
      # unset dotglob
      shopt -u dotglob
      
    • 使用 GLOBIGNORE 变量(也设置 dotglob):

      # Run git within a modified environment that includes GLOBIGNORE.
      GLOBIGNORE='.git' git rm *
      

    【讨论】:

      【解决方案3】:

      正如 user1281385 在评论中指出的那样,shell 第一次扩展 *

      second 时间删除点文件的原因是,一旦没有文件匹配,shell 就会将文字星号作为参数(无论如何取决于你的 shell,至少有一个变体而是出错),然后 git 会进行自己的匹配。

      【讨论】:

        【解决方案4】:

        注意正确的语法应该是git rm -r . ('dot')

        更令人担忧的是git rm -r(空路径规范字符串),它在 Git 2.11 之前也是如此!

        参见Emily Xie (emilyxxie)commit d426430(2016 年 6 月 22 日)。
        (由 Junio C Hamano -- gitster -- 合并到 commit 3b1e135,2016 年 10 月 26 日)

        pathspec:警告空字符串作为路径规范

        作为 pathspec 元素的空字符串匹配所有路径。
        然而,一个有缺陷的脚本可能会意外地将一个空字符串分配给一个变量,然后该变量会被传递给 Git 命令调用,例如:

        path=... compute a path to be removed in $path ...
        git rm -r "$paht"
        

        这会无意中删除当前目录中的所有路径。

        解决此问题需要两步方法。

        • 由于可能存在以这种方式故意使用空字符串的现有脚本,第一步只是给出一个警告,即 (1) 告诉空字符串将成为无效的 pathspec 元素,并且 (2) 询问用户 如果要匹配所有,请使用“.”。

        • 对于第二步,几个发布周期后的后续补丁将 删除警告并改为抛出错误。


        Git 2.15.x/2.16(2018 年第一季度)更新:

        消息“将在即将发布的版本中失效”消失,变为:

        empty string is not a valid pathspec.
        please use . instead if you meant to match all paths
        

        commit 9e4e8a6(2017 年 6 月 7 日)Emily Xie (emilyxxie)
        请参阅 Junio C Hamano (gitster)commit 229a95a(2017 年 6 月 23 日)。
        (由 Junio C Hamano -- gitster -- 合并于 commit 728c573,2017 年 11 月 6 日)

        作为 pathspec 元素的空字符串匹配所有路径。
        然而,一个有缺陷的脚本可能会意外地将一个空字符串分配给一个变量,然后该变量会被传递给 Git 命令调用,例如:

        path=... compute a path to be removed in $path ...
        git rm -r "$path"
        

        这会无意中删除当前路径中的所有路径 目录。

        【讨论】:

          猜你喜欢
          • 2023-03-09
          • 2017-02-11
          • 1970-01-01
          • 2018-08-27
          • 2019-12-06
          • 2014-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多