git笔记之ignore

在push到远程仓库中,往往要忽略中间文件和开发环境配置文件等文件的提交,这时就要设置相应的忽略规则,来自动忽略这些文件。

原则

Git忽略文件的原则

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

方式

有三种方法可以实现忽略Git中不想提交的文件

  1. 在项目中定义.gitignore文件
    在项目根目录下定义.gitignore 文件,它往往要提交到公有仓库中,为该项目下的所有开发者都预设定义好的忽略规则。.gitingore 文件每一行指定一个忽略规则。如:
*.log
*.temp
/vendor
  1. 在项目的设置中临时指定排除文件
    这种方式只是临时指定该项目的行为,需要编辑当前项目下的 .git/info/exclude文件,然后将需要忽略提交的文件写入其中。这种方式指定的忽略文件的根目录是项目根目录。

  2. 定义全局的 .gitignore 文件
    除了可以在项目中定义 .gitignore 文件外,还可以设置全局的git .gitignore文件来管理所有由git版本控制项目的行为。这种方式是定义个人开发机的全局环境,不在项目成员中共享。这种方式也需要创建相应的 .gitignore 文件,可以放在任意位置。然后在使用以下命令配置:

$ git config --global core.excludesfile ~/.gitignore

语法

匹配语法

  1. 空格不匹配任意文件,可作为分隔符,可用反斜杠转义
  2. #开头的行代表注释,git忽略,可以使用反斜杠进行转义
  3. .gitignore使用标准的glob模式匹配。glob模式)往往用于在类UNIX系统中匹配文件路径。
  4. 斜杠/开头表示目录,/结束的模式只匹配文件夹和该文件夹路径下的内容,/开始的模式匹配项目根目录
  5. 星号*通配多个字符,问号?通配单个字符, 使用两个星号**表示匹配任意中间目录
  6. 方括号[]包含单个字符的匹配列表,即匹配任何一个列在方括号中的字符。
  7. 感叹号!表示不忽略(跟踪)匹配到的文件或目录,即要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。如果文件的父目录已经被前面的规则排除掉了,那么对这个文件用”!”规则是不起作用的。也就是说”!”开头的模式表示否定,该文件将会再次被包含,如果排除了该文件的父级目录,则使用”!”也不会再次被包含。可以使用反斜杠进行转义。
  8. .git对于.ignore配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效!

优先级

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

  1. 从命令行中读取可用的忽略规则
  2. 当前目录定义的规则
  3. 父级目录定义的规则,依次递推
  4. $GIT_DIR/info/exclude 文件中定义的规则
  5. 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