我一直在使用git,但仍然对 .gitignore 文件路径感到困惑。
那么, .gitignore 文件中的以下两个路径有什么区别?
tmp/* public/documents/**/*
我可以理解tmp/*
会忽略其中的所有文件和文件夹。我对吗?
但是第二条线路的意思是什么?
答案 0 :(得分:55)
这取决于shell的行为。 Git没有做任何工作来确定如何扩展它们。通常,*
匹配任何单个文件或文件夹:
/a/*/z
matches /a/b/z
matches /a/c/z
doesn't match /a/b/c/z
**
匹配任何文件夹字符串:
/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
答案 1 :(得分:15)
如果你正在使用像Bash 4这样的shell,那么**本质上是*的递归版本,它将匹配任意数量的子目录。
如果在示例中添加文件扩展名,则更有意义。要在tmp中立即匹配日志文件,请键入:
/tmp/*.log
要在tmp的任何子目录中的任何位置匹配日志文件,请键入:
/tmp/**/*.log
但是使用git版本1.6.0.4和bash版本3.2.17(1)进行测试 - 释放,似乎git根本不支持** globs。 most recent man page for gitignore也没有提到**,所以这是(1)非常新,(2)不受支持,或(3)某种程度上依赖于系统的globbing实现。
此外,您的示例中还有一些微妙的内容。这个表达式:
tmp/*
...实际上意味着“在源树中的任何地方忽略 tmp目录中的任何文件,但不要忽略tmp目录本身”。在正常情况下,你可能只写:
/tmp
...会忽略单个顶级tmp目录。如果你确实需要保留tmp目录,而忽略它们的内容,你应该在每个tmp目录中放置一个空的.gitignore文件,以确保git实际上创建了目录。
答案 2 :(得分:15)
今天,我无法找到**
无效的机器。这包括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
无论我尝试什么,我都无法工作,但至少这与git docs一致。我怀疑,当人们将其添加到.gitignore
时,它会偶然起作用,因为他们的.obj
文件恰好是一个深度的子目录。他们可能从bash脚本中复制了双星号。但也许有些系统fnmatch(3)
可以像bash那样处理双星号。
答案 3 :(得分:14)
请注意,'**
',与子目录(**/bar
)结合使用时,必须更改其默认行为,因为{{3}现在提到:
.gitignore
和.gitattributes
文件中的模式可以有**/
,作为匹配0或更多级别子目录的模式。E.g。 “
foo/**/bar
”与“bar
”本身或“foo
”的子目录中的“foo
”匹配。
“
foo/**/bar
”匹配“foo/x/bar
”,“foo/x/y/bar
”......但不匹配“foo/bar
”。
我们提出了一个特殊情况,当检测到foo/**/
时(并且“foo/
”部分已经匹配),请尝试将“bar
”与其余字符串匹配。“匹配一个或多个目录”语义可以使用“
foo/*/**/bar
”轻松实现。除了“
**/foo
”,“foo
”之外,这也会使“x/foo
”与“x/y/foo
”匹配。签名:NguyễnTháiNgọcDuy
<pclouds@gmail.com>
commit 4c251e5cb5c245ee3bb98c7cedbe944df93e45f4也Simon Buchan:
当前文档(commented)非常明确,不需要子目录,
x/**
匹配(可能为空)x
下的所有文件
.gitignore
手册页确实提到了:
尾随“
/**
”匹配内部的所有内容。例如,“abc/**
”匹配目录“abc
”内的所有文件,相对于.gitignore
文件的位置,具有无限深度。斜杠后跟两个连续的星号,然后斜杠匹配零个或多个目录。例如,“
a/**/b
”匹配“a/b
”,“a/x/b
”,“a/x/y/b
”等等。
答案 4 :(得分:5)
当不支持**时,“/”本质上是通配符的终止字符,所以当你有类似的东西时:
public/documents/**/*
它本质上是在斜杠之间寻找两个通配符项,而不是自己获取斜杠。因此,这将与:
相同public/documents/*/*
答案 5 :(得分:2)
它对我不起作用,但你可以在该子目录中创建一个新的.gitignore
:
tmp/**/*.log
可以替换为.gitignore
中的tmp
:
*.log