.gitignore文件中路径的差异?

Aut*_*act 55 gitignore

我一直在使用git,但仍然对.gitignore文件路径感到困惑.

那么,.gitignore文件中以下两个路径之间有什么区别?

tmp/*
public/documents/**/*

我可以理解,tmp/*它将忽略其中的所有文件和文件夹.我对吗?但是第二条线路的意思是什么?

Joh*_*lla 55

这取决于shell的行为.Git没有做任何工作来确定如何扩展它们.通常,*匹配任何单个文件或文件夹:

/a/*/z
 matches        /a/b/z
 matches        /a/c/z
 doesn't match  /a/b/c/z
Run Code Online (Sandbox Code Playgroud)

** 匹配任何文件夹字符串:

/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
Run Code Online (Sandbox Code Playgroud)

结合**使用*以匹配整个文件夹树中的文件:

/a/**/z/*.pr0n
 matches        /a/b/c/z/d.pr0n
 matches        /a/b/z/foo.pr0n
 doesn't match  /a/b/z/bar.txt
Run Code Online (Sandbox Code Playgroud)

  • 不,它取决于fnmatch,而不是shell.bash-4支持这个,但是git在我的机器上忽略**,运行bash-4.我不知道任何**意味着什么.大多数人对此进行评论并未对其进行实际测试.如果你用git(而不是shell)测试了这个,请发布你的O/S. 试试`git -nv`进行测试. (14认同)
  • 你在测试`bash`或`git`吗?我毫不怀疑`bash`的工作方式与广告一样,至少在适当的设置下如此.`git -nv add .`是测试这些东西的方法.在准确地尝试了这些测试后,我几乎肯定"git"在MacOS上不能正常工作.也许Linux和MacOS上的`fnmatch`之间存在差异.(`git`使用`fnmatch`,而不是shell,用于此匹配.)你可以在MacOS上执行测试,仔细检查我自己的吗? (2认同)

cdu*_*001 16

更新(2016年3月8日)

今天,我无法找到一台**无法正常工作的机器.这包括OSX-10.11.3(El Capitan)和Ubuntu-14.04.1(Trusty).可能git-ignore已经更新,或者可能是人们期望的最近的fnmatch句柄**.所以现在接受的答案在实践中似乎是正确的.


原帖

**在没有特殊含义的git.它是bash> = 4.0,via的一个特性

shopt -s globstar

但是git不使用bash.要查看git实际上做了什么,您可以git add -nv在几个级别的子目录中试验和文件.

对于OP,我已经尝试了我能想到的每个文件组合.gitignore,没有比这更好的了:

public/documents/

以下并不是每个人都想到的事情:

public/documents/**/*.obj

无论我尝试什么,我都无法工作,但至少这与git docs一致.我怀疑当人们添加它时.gitignore,它是偶然的,只是因为他们的.obj文件恰好是一个深度的子目录.他们可能从bash脚本中复制了双星号.但也许有些系统fnmatch(3)可以像bash那样处理双星号.


emk*_*emk 15

如果您使用的是诸如Bash 4之类的shell,则**本质上是*的递归版本,它将匹配任意数量的子目录.

如果在示例中添加文件扩展名,则更有意义.要在tmp中立即匹配日志文件,您可以键入:

/tmp/*.log
Run Code Online (Sandbox Code Playgroud)

要在tmp的任何子目录中的任何位置匹配日志文件,您可以键入:

/tmp/**/*.log
Run Code Online (Sandbox Code Playgroud)

但是使用git版本1.6.0.4和bash版本3.2.17(1)进行测试 - 发布,似乎git根本不支持**globs.在对gitignore最近的手册页没有提到**,要么,所以这是(1)很新,(2)不支持,或(3)在某种程度上取决于系统的实现通配的.

此外,您的示例中还有一些微妙的内容.这个表达式:

tmp/*
Run Code Online (Sandbox Code Playgroud)

...其实就是"忽略任何文件一个tmp目录,在源代码树的任何地方,但不要忽略TMP目录本身".在正常情况下,你可能只写:

/tmp
Run Code Online (Sandbox Code Playgroud)

...会忽略单个顶级tmp目录.如果你确实需要保留tmp目录,而忽略它们的内容,你应该在每个tmp目录中放置一个空的.gitignore文件,以确保git实际创建了该目录.

  • 答案是(3):手册页清楚地表明glob将被未经修改地传递给系统的fnmatch库函数.因此,gitignore globs的行为取决于系统. (6认同)

Von*_*onC 14

请注意,' **' 与子目录(**/bar)结合使用时,必须更改其默认行为,因为git1.8.2发行说明现在提到:

.gitignore.gitattributes文件中的模式可以**/作为匹配0或更多级别子目录的模式.

例如" foo/**/bar"匹配" bar"在" foo"本身或" "的子目录中foo.


请参阅commit 4c251e5cb5c245ee3bb98c7cedbe944df93e45f4:

" 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>


Simon Buchan评论道:

当前的文档(.gitignore手册页)很清楚,不需要子目录,x/**匹配(可能为空)下的所有文件x

.gitignore手册页确实提到:

尾随" /**"匹配内部的一切.例如," abc/**"匹配目录" abc" 内的所有文件,相对于.gitignore文件的位置,具有无限深度.

斜杠后跟两个连续的星号,然后斜杠匹配零个或多个目录.例如," a/**/b"匹配" a/b"," a/x/b"," a/x/y/b"等.


Haz*_*zok 5

当不支持**时,"/"本质上是通配符的终止字符,所以当你有类似的东西时:

public/documents/**/*
Run Code Online (Sandbox Code Playgroud)

它本质上是在斜杠之间寻找两个通配符项,而不是自己获取斜杠.因此,这将是:

public/documents/*/*
Run Code Online (Sandbox Code Playgroud)