工作经历
公司有时候把一些项目交给一些不熟悉Git的人来管理,他们从服务器下载了代码后,不去先执行Git仓库初始化,而是先去编译代码。代码编译完成之后,会生成很多中间文件(例如日志文件,临时文件等等),然后他们把代码,并且连带这些中间文件,一起提交了。我们下载了这个Git仓库代码,每交编译完成,通过Git查看状态,会发现一大堆的已修改的中间文件,非常碍眼。
正确的方式应该是下载代码后,先初始化Git仓库,把代码纳入Git管理。再编译代码,查看生成的中间文件的,创建
.gitignore
文件来忽略这些中间文件。
.gitignore 规则
.gitignore
文件有以下规则
- 以#开关的行是注释行,它会被Git忽略 。
- 它使用标准的 glob 模式进行匹配,并且会递归地应用在整个工作区中。
- 匹配模式以 / 开头,表示匹配的是当前目录。
- 匹配模式以 / 结尾,表示匹配的是目录。
- 如果在模式前面加上感叹号,表示规则取反。
glob 模式
这些规则,就只有一个难点,什么是 glob 模式? 规则如下
- 星号(*)匹配零个或者多个任意字符。
- 问号(?)只匹配一个字符。
-
匹配括号内的任意一个字符,例如[]
匹配a 或 b 或 c,[abc]
匹配所有的小写字符,[a-z]
匹配所有数字。[0-9]
-
匹配任意中间目录 ,例如**
可以匹配ac
,也可以匹配a/b/c
。a/b/d/c
这里的glob模式和Vim中搜索文件路径中所使用的glob模式是一样的,但是不知道与shell中的通配符是否有关系。
例子
假如现在 Git 仓库下,经过编译后,有如下的生成文件
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
dir1/world.o
hello.o
out/
build/out/result.txt
有两个以
.o
结尾的文件,一个在当前目录下,一个在 dir1 目录下,如果我们想同时忽略这两个文件,可以在
.gitignore
中增加如下一行
# 递归整个工作区,忽略所有以 .o 结尾的文件
`*.o`
这两个中间文件不在同一个目录,为何会同时忽略?注意规则2所说的,glob 模式会递归地应用到整个工作区。
如果我们只想忽略除了 hello.o 以下的其它中间文件,那么可以使用如下命令
# 递归整个工作区,忽略所有的以 .o 结尾的文件
*.o
# 但是排除 hello.o
!hello.o
如果我们只想忽略当前目录下的 out 目录,那么添加如下一行
# 忽略当前目录下的 out 目录
/out/
第一个 / 表示当前目录,第二个 / 表示 out 是一个目录。
在工作区中,有两个 out 目录 ,如果我们想同时忽略它们,可以添加如下一行
# 递归整个工作区,忽略所有的 out 目录
out/
/out/
与
out/
的区别在于,
/out/
只忽略当前目录下的 out 目录,而
/out/
会递归忽略所有目录下 out 目录。
如果使用
**
来忽略
build/out/result.txt
,可以写成
/build*.o
。
如果想忽略 build 目录以及子目录下的所有的 result.txt 文件,那么可以使用
**
# 忽略build目录以其子目录下的所有result.txt文件
/build/**/result.txt