全面解析.gitignore文件中的模式匹配。
.gitignore文件里的模式匹配有时真的让人很无语,看似非常简单,实则到处是坑,
本文我们来个彻底解析。本文来自git文档加上自己的理解,以及总结了一些常用实例,
git文档可以参考文末的链接。
语法(pattern format)
第一部分语法规则
- 空行被忽略
- 以
#
开头的行视为注释,需要#
的地方要进行转意 - 其余每行表示一个pattern
- 行尾 的空格被忽略,需要行尾空格的地方要进行转意
!
意味着取反
,即原本被匹配上的文件被忽略,加上!
后,
这些文件则被包含进来,需要!
的地方要要进行转意。
但是如果一个文件的parent directory被忽略,则该文件不会被包含进来。- 以
/
结尾的pattern,/
将会被移除,然后按照下面的规则进行匹配,但是只匹配目录 - 如果pattern中没有
/
,则git把该pattern当作一个shell glob去匹配文件路径 - 如果pattern中包含
/
,则git把该pattern当作一个受限的shell glob去匹配文件路径:
此时wildcards(*
)不能匹配/
符号 - 以
/
开头的pattern,/
匹配文件路径的开始,如/*.c
匹配cat.c
而不匹配mozilla/cat.c
语法一大堆,但是真正值得注意的地方是:
/
和*
,即pattern中有/
的时候*
不匹配/
,
pattern中没有/
的时候*
可以匹配/
- 以
/
结尾的pattern会去掉/
进行匹配,但是只匹配目录,如*/
会匹配所有的目录,
这一点常常结合!
不能把父目录被忽略的文件重新包含进来这条规则来用
pattern format定义好了,而pattern要跟谁进行匹配呢,答案是跟文件路径,文件路径指的是
从git repository开始的相对文件路径。git会遍历所有的文件,用这里定义的pattern来进行
匹配,匹配的结果就是要么包含进版本库,要么忽略它。
第二部分,双星号语法规则
**
匹配完整路径,它不管什么斜杠不斜杠的,所有字符通吃。
- 以
**/
开始的pattern匹配所有路径。如**/foo
匹配所有路径下的foo
文件或者文件夹,
等同于foo
pattern - 以
/**
结尾的pattern匹配everything inside。如abc/**
匹配abc
目录下的所有文件或文件夹 - 中间包含
/**/
的pattern匹配零个或任意多个目录。如a/**/b
匹配a/b
、a/x/b
、a/x/y/b
等等 - 上述三种pattern的组合pattern
这里的**
类似于正则表达式里的*
。
常用实例
下面列出一些常用实例,日常使用足够了。
忽略某个文件夹
1 | # 忽略build目录 |
忽略某类文件
1 | # 忽略所有的.exe文件 |
忽略某个文件夹,但是保留某些特殊文件
1 | # 忽略build目录,但是保留build/config.xml文件 |
建立白名单,只保留某些文件夹或者目录
所谓的白名单就是先忽略所有的文件、文件夹,然后把需要的再重新包含进来,
但是注意:parent dir被忽略的文件是不能被重新包含进来的。1
2
3
4
5
6
7
8
9
10
11
12
13# 忽略一切
*
# 把所有的文件夹重新包含进来
# 这是怎么做到的呢? 看第6条规则
!*/
# 把想要的文件或文件夹重新包含进来
# 这里为啥不能用: !src/* 呢,因为有斜杠时星号不能匹配斜杠,
# 导致src/里的子目录被忽略了,只包含进src/下的文件了
# 这里为啥不能用: !src/ 呢,因为以斜杠(/)结尾只能匹配目录
!src/**
!AndroidManifest.xml
# 如果不把所有文件夹包含进来,则需要先把res/目录包含进来才行
!res/drawable/**