git处理文件换行符

[TOC]

有时我们会遇到跨平台开发的情况,在windows上开发同时支持linux和windows部署的程序。
那么我们的程序中可能就会有平台相关的一些文件,比如shell脚本(bat、sh)。
如果没有正确处理好这些文件的换行符,将会导致脚本文件在对应的平台上不能正确执行。

对于使用Git管理源码的项目,git对text文件有自动转换换行符的机制,相关的配置有:

  • git config core.autocrlf
  • git config core.safecrlf
  • git config core eol
  • .gitattributes

windows和linux换行符的区别

  • 在linux系统中,行尾使用一个换行符(LF=line feed)表示
  • 在windows系统中,行尾使用回车(CR=carriage return)+换行(LF=line feed)2个字符表示

git config core.autocrlf

可选的配置值有:

  • true 提交文件时自动转换为LF,检出文件时自动转换为CRLF。在windows平台上,这个是git的默认设置。
  • input 提交的时候自动转换为LF,检出文件时不做转换。
  • false 提交和检出的时候都不对换行符进行自动转换。提交时文件时什么样,服务器上就是什么样。
    1
    2
    3
    4
    5
    6
    7
    core.autocrlf=true:    core.autocrlf=input:      core.autocrlf=false:

    repo repo repo
    ^ V ^ V ^ V
    / \ / \ / \
    crlf->lf lf->crlf crlf->lf \ / \
    / \ / \ / \

因为 core.autocrlf 在windows平台上默认是true,所以检出的时候sh文件将自动转换成CRLF换行符。
如果在windows平台上打包安装程序,那么安装后的程序sh文件将不能正常执行。

git config core.safecrlf

由于git有自动转换换行符的机制,如果设置了autocrlf,那么文件的换行符可能被统一处理。
例如: 对于混合了CRLF和LF的文件,都被统一成LF提交服务器了。

这种就是git处理转换后不可逆的情况:在同个机器上,提交后再检出,不能还原出一样的文件。
如果git错误的将binary文件判断为text文件,自动进行了CRLF转换,那么就会损坏文件数据。

通过开启 safecrlf 选项,可以防止出现上述错误:

  • true 如果git根据配置的CRLF转换自动处理文件,将导致文件不可逆,那么git将拒绝提交文件。
  • warn 如果git根据配置的CRLF转换自动处理文件,将导致文件不可逆,那么git将显示警告信息但继续处理文件。
  • false 关闭检查。

开启该选项不会改变git的CRLF转换处理,但通过该选项,可以保证提交的text文件里不会出现混合LF、CRLF的情况。

git config core.eol

当autocrlf=false时,通过.gitattributes配置了text属性的文件,其换行符将使用本配置值。
可选的值有:cr,crlf,native(使用本地操作系统匹配的换行符)

.gitattributes

在项目的git根路径下,添加.gitattributes文件并纳入git管理,然后打开编辑内容:

1
2
3
4
5
6
7
8
9
10
11
*.bat eol=crlf
*.sh eol=lf

*.jpg -text
*.png -text
*.pdf -text

*.exe -text
*.so -text

*.txt text=auto

说明:

  • bat 文件在检入检出时,使用CRLF换行符
  • sh 文件在检入检出时,使用LF换行符
  • ‘-text’ 的意思是,标记该类型的文件不是text。git对这类文件会跳“是否text文件”的检测,也不会自动转换换行符。
  • ‘text=auto’ 的意思是,标记该类型的文件是text,同时使用core.eol配置的换行符(如果有配置的话)。
  • 优先级: autocrlf > text=auto + core.eol

对于明确是二进制数据的文件,可以在本文件中显示的声明非text,防止git检测有误时错误的对文件进行处理而损坏数据。

总结

通过git config进行配置,只能在对所有的文件进行统一处理,不能分文件类型处理。
而且仅对各客户端有效,不能保证在不同开发人员那保持一致。
所以最好在项目根路径下添加.gitatttibutes文件,对关键的文件类型分别统一配置CRLF转换,也可避免不同客户端环境不同的影响。

参考