在 push 到远程仓库中,往往要忽略中间文件和开发环境配置文件等文件的提交,这时就要设置相应的忽略规则,来自动忽略这些文件。
原则
Git 忽略文件的原则
- 忽略操作系统自动生成的文件,例如 macOS 中的
.DS_Store - 忽略编译生成的中间文件、可执行文件等,如果一个文件是通过另一个文件自动生成的,那么就没必要放进版本库,比如 Java 编译产生的
.class文件 - 忽略带有敏感信息的配置文件,比如存放口令的配置文件
方式
有三种方法可以实现忽略 Git 中不想提交的文件:
- 在项目中定义.gitignore 文件
在项目根目录下定义.gitignore 文件,它往往要提交到公有仓库中,为该项目下的所有开发者都预设定义好的忽略规则。.gitingore 文件每一行指定一个忽略规则。如:
*.log
*.temp
/vendor
在项目的设置中临时指定排除文件
这种方式只是临时指定该项目的行为,需要编辑当前项目下的.git/info/exclude文件,然后将需要忽略提交的文件写入其中。这种方式指定的忽略文件的根目录是项目根目录。定义全局的 .gitignore 文件
除了可以在项目中定义.gitignore文件外,还可以设置全局的 git.gitignore文件来管理所有由 git 版本控制项目的行为。这种方式是定义个人开发机的全局环境,不在项目成员中共享。这种方式也需要创建相应的 .gitignore 文件,可以放在任意位置。然后在使用以下命令配置:
$ git config --global core.excludesfile ~/.gitignore
语法
匹配语法
- 空格不匹配任意文件,可作为分隔符,可用反斜杠转义
#开头的行代表注释,git 忽略,可以使用反斜杠进行转义.gitignore使用标准的 glob 模式匹配。glob 模式 ) 往往用于在类 UNIX 系统中匹配文件路径。- 斜杠
/开头表示目录,/结束的模式只匹配文件夹和该文件夹路径下的内容,/开始的模式匹配项目根目录 - 星号
*通配多个字符,问号?通配单个字符, 使用两个星号**表示匹配任意中间目录 - 方括号
[]包含单个字符的匹配列表,即匹配任何一个列在方括号中的字符。 - 感叹号
!表示不忽略 (跟踪) 匹配到的文件或目录,即要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。如果文件的父目录已经被前面的规则排除掉了,那么对这个文件用”!”规则是不起作用的。也就是说”!”开头的模式表示否定,该文件将会再次被包含,如果排除了该文件的父级目录,则使用”!”也不会再次被包含。可以使用反斜杠进行转义。 - .git 对于.ignore 配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效!
优先级
在 .gitingore 文件中,每一行指定一个忽略规则,Git 检查忽略规则的时候有多个来源,它的优先级如下(由高到低):
- 从命令行中读取可用的忽略规则
- 当前目录定义的规则
- 父级目录定义的规则,依次递推
- $GIT_DIR/info/exclude 文件中定义的规则
- core.excludesfile 中定义的全局规则
例:
*.a #忽略所有目录中所有 .a 结尾的文件
/*.b #忽略根目录中所有 .b 结尾的文件
**/*.c #忽略所有目录中子目录中的 .c 结尾的文件
!/1.b #不忽略根目录下的 1.b 文件
bin/ #忽略当前路径下的 bin 文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件
/bin #表示忽略根目录下的 bin 文件
a/**/b #表示忽略 a 目录下所有目录及其子目录中的 b 文件,例如 a/b, a/c/b , a/c/d/b
⚠️
如果如果在版本库中写 .gitignore 文件之前就已经提交了要忽略的文件,那么 Git 仍然会对这些文件进行版本管理。例如已经 commit 了 1.a 这个文件到版本库,再写入 1.a 这条忽略规则到 .gitignore 文件,那么这条规则就失效了。对 1.a 文件的修改仍然会被版本控制。这种情况的解决方式可以参看git rm 删除版本控制。
查看规则
我们可以用 git check-ignore 命令检查忽略规则:
$ git check-ignore -v ./bin/root-bin.a
.gitignore:2:/bin ./bin/root-bin.a
可以看到 ./bin/root-bin.a 匹配到了我们的第二行 /bin 的忽略规则,所以文件被忽略了。
删除本地缓存
有的时候已经在.gitignore 中标明忽略的文件,但 git status 中该文件依旧处于 tracted 状态,这是因为在 git 忽略目录中,新建的文件会有缓存,如果某文件已经被纳入版本管理,那么再在.gitignore 中声明也是无效的,此时需要删除本地缓存,这样不会直接删除文件。如果去掉 --cached 选项则是直接删除对应文件。
$ git rm -r --cached .
$ git add .
$ git commit -m ".gitignore updated"
远程仓库中删除版本控制
有的时候想移除远程仓库中的某些文件的版本控制,但依旧在本地保留该文件。这时候不可以直接使用 git rm directory,这样会删除本地仓库的文件。可以使用git rm -r –cached directory 来删除本地缓存,然后进行 commit 和 push,这样会发现远程仓库中的不必要文件就被删除了,以后可以直接使用 git add -A 来添加修改的内容,上传的文件就会受到.gitignore 文件的内容约束。
$ git rm -r --cached 1.a
$ git add -A
$ git commit -m "update .gitignore"
$ git push origin