git rm *不会一次性删除所有文件

时间:2013-10-14 15:31:20

标签: 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 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

4 个答案:

答案 0 :(得分:23)

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

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

git rm -r folder testfile3

,第二个可能是文字

git rm -r *

git然后自行扩展。

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

git rm -r '*'

答案 1 :(得分:5)

Shell Globbing

运行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 *
    

答案 2 :(得分:4)

正如评论中提到的user1281385一样,shell第一次扩展*

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

答案 3 :(得分:0)

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

更令人担忧的是git rm -r(空路径规范字符串),直到Git 2.11才会这样做!

commit d426430Emily Xie (emilyxxie)(2016年6月22日) Junio C Hamano -- gitster --于2016年10月26日commit 3b1e135合并)

  

pathspec:警告空字符串为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 9e4e8a6Emily Xie (emilyxxie)(2017年6月7日) 请commit 229a95a查看Junio C Hamano (gitster)(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"
  

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