gitattributes

简介

该配置文件可以控制git各种命令的行为。例如执行git diff时是否对比二进制文件内部差异,亦或者使用自定义的diff方法去对比文件,例如控制git如何去merge两个文件,还有个最常用的应用场景就是对换行符的处理,下面会提到。

.gitattributes 文件的配置形式为:

# 要匹配的文件    属性1 属性2 ...
pattern attr1 attr2 ...

例如:

*           text=auto  
# 文件的行尾自动转换。如果是文本文件,则在文件入Git库时,行尾自动转换为LF。如果已经在入Git库中的文件的行尾是GRLF,则文件在入Git库时,不再转换为LF。

*.txt       text  
# 对于.txt文件,标记为文本文件,并进行行尾规范化。

*.jpg       -text  
# 对于`.jpg`文件,标记为非文本文件

*.vcproj    text eol=crlf 
# 对于.vcproj文件,标记为文本文件,在文件入Git库时进行规范化,行尾转换为LF。在检测到出工作目录时,行尾自动转换为CRLF。

*.sh        text eol=lf  
# 对于sh文件,标记为文本文件,在文件入Git库时进行规范化,即行尾为LF。在检出到工作目录时,行尾也不会转换为CRLF(即保持LF)。

*.py        eol=lf  
# 对于py文件,只针对工作目录中的文件,行尾为LF。

*.bat       text eol=crlf 
# 无格式的文本文件,保证 Windows 的批处理文件在 checkout 至工作区时,始终被转换为 CRLF 风格的换行符;

*.bin	       binary
# bin文件为二进制文件处理

同gitignore一样,第一列为需要匹配的文件,可以为目录,当为目录时就是匹配该目录下所有的文件(不会递归匹配二级目录下的文件,这点和gitignore不同)

右边则为属性,例如上面配置文件中,text、eol、binary 均为属性,所有的属性都有4个状态:set、unset、unspecified、set a value

当为set状态时,则会设置该属性的值为true,例如上文中的 text 或 binary,该属性为true则会将匹配的文件视为text/binary文件处理。与之相反的状态为unset(视为text类型就能处理换行符,也就是下面的eol属性会生效,如果为binary则eol就不会生效)

当为set a value 状态时,则会使用该值,例如上文中的 eol,它用来配置如何处理文本文件的换行符,当它设置为lf时,它就会保证在git仓库中的文件结尾都为lf(如果原本时crlf则在提交到版本库时也会自动转成lf)

gitattributes提供了很多属性可以设置,其中就包含例如 text、diff、merge等,具体参见官方文档

.gitattributes文件可以有多个,例如项目的不同文件夹下放不同的.gitattributes,如果同一个文件匹配到多条规则,则以后面的为准。

换行符问题

当前,windows则使用CRLF作为换行符,而unix、linux、macos都使用LF标记作为换行符,但它们也兼容CRLF,故当的项目同时在linux和windows下进行开发时,就会出现问题。

所幸git也考虑到了这个问题,所以它默认会开启一个换行符自动转换的功能。git版本库所有的代码需保证换行符为LF,所以在windows下,当你checkout代码时,它就会自动将所有的LF替换成CRLF,当你commit时又会将所有的CRLF替换成LF。所以一般来说外国人就没有换行符的困扰。

不幸的是这个自动转换功能是有bug的,当文件内容中有utf8编码的中文时该功能可能失效,即它还是会将CRLF保存进版本库。具体表现在你将windows开发的代码通过git传到linux上时,通过git diff就可能会看到所有的文件所有的行都会被标记为已修改,当然是换行符导致的。这是因为你版本库保存的是CRLF,而在linux下checkout时又会转换为LF,所以diff就出现了。

解决办法有两种,一种是在本地使用命令行修改默认行为,但这种做法就只能限制你自己,别人如果不做配置也会出问题,更好的方法就是使用.gitattributes,限制git强制只使用LF,例如上文中的 *.py*.sh 配置 。

JetBrains IDE可以在右下角设置

Leave a Comment