8

我正在尝试 git 的一些示例指令,并遇到了一个特殊的情况,即当我们执行 a 时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 根目录的文件会发生这种情况?

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

我正在使用 git 版本1.7.9.5

4

4 回答 4

25

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

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

git rm -r folder testfile3

第二个可能是文字

git rm -r *

然后git自行扩展。

正如基思所说,要一次性删除所有内容,请防止外壳扩展通配符,以便git第一次进行扩展。这可以使用双引号或单引号来完成,或者在星号前使用反斜杠。我更喜欢单引号:

git rm -r '*'
于 2013-10-14T15:37:55.063 回答
6

壳牌通配符

当您运行时,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 *
    
于 2013-10-14T17:00:14.683 回答
4

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

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

于 2013-10-14T15:39:28.727 回答
0

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

更令人担忧的是git rm -r(empty pathspec string) 在 Git 2.11 之前也是如此!

请参阅Emily Xie ( )的提交 d426430(2016 年 6 月 22 日) 。(由Junio C Hamano 合并 -- --提交 3b1e135中,2016 年 10 月 26 日)emilyxxie
gitster

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

请参阅Emily Xie ( )的提交 9e4e8a6(2017 年 6 月 7 日) 。 请参阅Junio C Hamano ( ) 的提交 229a95a(2017 年 6 月 23 日(由Junio C Hamano 合并——提交 728c573中,2017 年 11 月 6 日)emilyxxie
gitster
gitster

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

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

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

于 2016-10-28T21:07:00.500 回答