.gitignore文件中的path差异?
我一直在使用git,但仍然对.gitignore文件path感到困惑。
那么, .gitignore文件中以下两个path有什么区别?
TMP / * 公共/文件/ ** / *
我可以理解, tmp/*
将忽略其中的所有文件和文件夹。 我对吗? 但是,第二条线路是什么意思?
这取决于你的shell的行为。 Git没有做任何工作来确定如何扩展这些。 通常, *
匹配任何单个文件或文件夹:
/a/*/z matches /a/b/z matches /a/c/z doesn't match /a/b/c/z
**
匹配任何string的文件夹:
/a/**/z matches /a/b/z matches /a/b/c/z matches /a/b/c/d/e/f/g/h/i/z doesn't match /a/b/c/z/d.pr0n
将**
与*
结合以匹配整个文件夹树中的文件:
/a/**/z/*.pr0n matches /a/b/c/z/d.pr0n matches /a/b/z/foo.pr0n doesn't match /a/b/z/bar.txt
如果你使用的是诸如Bash 4之类的shell,那么**本质上就是*的recursion版本,它将匹配任意数量的子目录。
如果你添加一个文件扩展名到你的例子,这样做更有意义。 要在tmp内部立即匹配日志文件,可以input:
/tmp/*.log
要在tmp的任何子目录中的任何地方匹配日志文件,你应该input:
/tmp/**/*.log
但使用git版本1.6.0.4和bash版本3.2.17(1)进行testing,发现git根本不支持** globs。 gitignore的最新手册页也没有提到**,所以这个或者是(1)非常新的,(2)不被支持的,或者(3)依赖于你的系统的globbing实现。
另外,在你的例子中还有一些微妙之处。 这个expression式:
tmp/*
实际上意味着“忽略源树中任何位置的tmp目录中的任何文件,但不要忽略tmp目录本身”。 在正常情况下,你可能只会写:
/tmp
…将忽略单个顶级tmp目录。 如果你需要保留tmp目录,而忽略它们的内容,你应该在每个tmp目录中放置一个空的.gitignore文件,以确保git实际创build目录。
更新(08-Mar-2016)
今天,我无法find一台机器**
没有声称工作。 包括OSX-10.11.3(El Capitan)和Ubuntu-14.04.1(Trusty)。 可能是git-ignore被更新,或者可能是最近的fnmatch句柄**
。 所以现在接受的答案在实践中似乎是正确的。
原帖
这个**
在git中没有特别的意义。 这是bash> = 4.0的一个特性,通过
shopt -s globstar
但是git不使用bash 。 要看看git实际上做了什么,可以尝试使用git add -nv
和几个级别的子目录中的文件。
对于OP,我已经试过了我能想到的.gitignore
文件的所有组合,没有什么比这更好的了:
public/documents/
以下不是每个人都想到的:
public/documents/**/*.obj
无论我尝试什么,我都无法工作,但至less与git文档是一致的。 我怀疑当人们把它添加到.gitignore
,它是偶然的,只是因为它们的.obj
文件恰好是一个子目录。 他们可能从bash脚本中复制了双星号。 但也许有一些系统, fnmatch(3)
可以像bash一样处理双星号。
请注意, **
和子目录 ( **/bar
) 结合在一起时 ,必须改变其默认行为,因为git1.8.2的发行说明现在提到:
.gitignore
和.gitattributes
文件中的模式可以具有**/
,作为匹配0或更多级子目录的模式。例如“
foo/**/bar
”与“foo
”本身或“foo
”的子目录中的“foo/**/bar
”相匹配。
参见提交4c251e5cb5c245ee3bb98c7cedbe944df93e45f4 :
“
foo/**/bar
”匹配“foo/x/bar
”,“foo/x/y/bar
”…但不是“foo/bar
”。
我们做一个特例,当foo/**/
被检测到(和“foo/
”部分已经匹配)时,尝试将“bar
”与其余的string进行匹配。“匹配一个或多个目录”语义可以使用“
foo/*/**/bar
”轻松实现。这也使得“
**/foo
”除了“x/foo
”,“x/y/foo
”之外还匹配“x/y/foo
”。签名:NguyễnTháiNgọcDuy
<pclouds@gmail.com>
Simon Buchan也评论道 :
当前文档(
.gitignore
手册页 )很清楚,不需要子目录,x/**
匹配所有文件(可能是空的)x
.gitignore
手册页确实提到:
尾随“
/**
”匹配里面的所有内容。 例如,“abc/**
”匹配目录“abc
”内的所有文件,相对于.gitignore
文件的位置,具有无限深度。斜杠后跟两个连续的星号,则斜线匹配零个或多个目录。 例如,“
a/**/b
”匹配“a/b
”,“a/x/b
”,“a/x/y/b
”等等。
当**不被支持时,“/”基本上是通配符的终止字符,所以当你有这样的东西时:
public/documents/**/*
它基本上是在两个斜杠之间寻找两个通配符,并且不会自己去掉斜线。 因此,这将是相同的:
public/documents/*/*
它不适用于我,但你可以在该子目录中创build一个新的.gitignore
:
tmp/**/*.log
可以在tmp
中用.gitignore
replace:
*.log