Git 吉特rm*没有';不要一次删除所有文件

Git 吉特rm*没有';不要一次删除所有文件,git,Git,我尝试了一些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

我尝试了一些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根目录的文件才会发生这种情况

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


我使用的是git版本
1.7.9.5

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

因此,当执行git时,第一个命令已经变为

git rm -r folder testfile3
第二个可能是文字

git rm -r *
git
然后自行展开

要一次性删除所有内容,请防止shell扩展通配符,以便
git
第一次进行扩展。这可以用双引号或单引号完成,也可以在星号前加反斜杠。我倾向于单引号:

git rm -r '*'

正如user1281385在一条评论中所指出的,shell第一次扩展了
*

第二次删除点文件的原因是,一旦没有要匹配的文件,shell将保留文字星号作为参数(取决于您的shell,至少会有一个变量出错),git将自己进行匹配。

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

  • 使用shopt内置:

  • 使用GLOBIGNORE变量(该变量还设置dotlob):


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

更令人担忧的是
gitrm-r
(空的pathspec字符串),它在git2.11之前都是这样做的

参见(2016年6月22日)作者。
(于2016年10月26日合并)

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

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

解决此问题需要两步方法

  • 由于可能存在故意以这种方式使用空字符串的现有脚本,因此第一步仅给出一个警告(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
参见(2017年6月7日)作者。
参见(2017年6月23日)作者。
(于2017年11月6日合并)

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

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


*将由您的shell解释,检查其全局规则控件x将扩展*以便您可以看到它没有一个答案提到解决方案:如果您希望git解释
*
,则需要引用或转义它:
git rm-r'*'
# Run git within a modified environment that includes GLOBIGNORE.
GLOBIGNORE='.git' git rm *
path=... compute a path to be removed in $path ...
git rm -r "$paht"
empty string is not a valid pathspec.
please use . instead if you meant to match all paths
path=... compute a path to be removed in $path ...
git rm -r "$path"