忽略特殊文件

.gitignore介绍

在使用 Git 的过程中,我们希望不提交工作目录中的一些文件,比如日志,临时文件等。就可以在 Git 工作区的根目录下创建一个特殊的 .gitignore 文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。

另外我们不需要从头写 .gitignore 文件,GitHub 开源了一个项目:github/gitignoreopen in new window,里面已经提供了很多模板。


.gitignore 忽略文件的原则是:

  • 忽略操作系统自动生成的文件,比如缩略图等;
  • 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如 Java 编译产生的 .class 文件;
  • 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

.gitignore 忽略规则的优先级 在 .gitingore 文件中,每一行指定一个忽略规则,Git 检查忽略规则的时候有多个来源,它的优先级如下(由高到低):

  1. 从命令行中读取可用的忽略规则【优先级高】
  2. 当前目录定义的规则
  3. 父级目录定义的规则,依次递推
  4. $GIT_DIR/info/exclude 文件中定义的规则
  5. core.excludesfile 中定义的全局规则【优先级低】

.gitignore匹配语法

在 .gitignore 编写规则,一行即一条规则,不区分大小写。

符号说明
空格不匹配任意文件,可作为分隔符,可用反斜杠转义
# 开头的是注释,都会被 Git 忽略,可以使用反斜杠进行转义
/ 开始/ 开始则匹配绝对路径,只从项目根目录开始进行匹配;
不以 / 开始则是匹配相对路径,会递归进行匹配
如:frotz 匹配 frotza/frotz/frotz 只匹配 frotz ,不匹配 a/frotz
/ 结束/ 结束则只匹配目录以及在该目录里面的内容,不匹配文件
不以 / 结束则匹配目录、目录下的内容,和文件
*通配符,匹配多个任意字符
**匹配任意中间目录
?通配符,匹配单个任意字符
[]匹配任何一个列在方括号中的字符。比如 [abc] 表示要么匹配一个 a,要么匹配一个 b,要么匹配一个 c
[0-9]在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配
!非,取反的意思,即不忽略匹配到的文件或目录
注意:如果文件的父目录已经被已有的规则排除掉了,那么再对里面的子文件用 ! 规则是不起作用的

以上特殊字符如果出现在文件或目录名中,可使用 \ 反斜杠进行转义。如:!\!important!.txt

TIP

git 对于 .ignore 配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效。

校验规则是否生效

通过 git check-ignore 命令可以检查文件是否被 .gitignore 忽略。

命令格式:

git check-ignore [options] pathname…

options 选项:
1. -v 显示匹配的详细信息
1
2
3
4

例如:

$ git check-ignore -v A/t1
.gitignore:3:A/ A/t1
1
2

从打印结果可以看到,在 .gitignore 文件的第3行有一条 A/ 的规则忽略掉了 A 目录下的 t1 文件。

特殊案例

只要A目录中的t1文件

场景:A 目录下包含 t1、t2、t3等文件,但是只需要跟踪 t1 文件,其他文件忽略。

正确规则如下:

/A/*
!/A/t1
1
2

错误案例:

/A/
!/A/t1
1
2

上面规则最后会发现 !/A/t1 并没有生效,t1 仍然被忽略掉了。

已经跟踪过的文件忽略规则不生效

现在,有文件 t1 之前已经 add 或 commit 跟踪过了,后面发现不需要对其进行跟踪,在 .gitignore 中加入过滤规则。在这种情况下,发现即使添加过滤规则后,文件 t1 仍然在被跟踪,没有被忽略掉。


场景一:t1 add 了,但是没有 commit。使用下面命令:

# 不写 pathname 则取消所有文件的 add
git reset HEAD pathname
# 重新 add
git add .
1
2
3
4

场景二:t1 已经commit了。

# 删除的本地缓存
git rm -r --cached .
# 重新 add
git add .
1
2
3
4

通过 git status 可以看到 t1 文件的状态为 deleted

参考资料