首先要理解的一点是,对于不同的操作系统,对于换行符的表示是不一样的。也就是说当我们在编辑一个文件,在键盘上按下回车键的时候,对于不同的操作系统保存到文件中的换行符是不一样的。见下表:
CR:表示回车\r
LF:表示换行\n
CRLF:表示回车换行\r\n
敲下回车键,不同的操作系统保存到文件中的值:
Windows:使用的是CRLF ==> 即\r\n,文件中保存的是\r\n
Linux/Unix: 使用的是LF ==> 即\n,文件中保存的是\n
Mac OS: 使用的是CR ==> 即\r,文件中保存的是\r
Mac OS X系统:使用的是LF ==> 即\n,文件中保存的是\n(Mac OS X已经改成和Unix/Linx一样使用LF)
问题: 既然不同的操作系统,对于换行符使用不同的表示形式,如果一个团队在开发一个共同的项目,如果你使用的是windows系统,而你的小伙伴用的是Mac的话,当你们使用git协同开发软件时,就会出现换行符不统一的问题。
虽然对于不同的操作系统,默认的换行符的表示方法不一样,但是编辑器是可以设置在敲下回车键的时候保存的换行符是什么的,比如常用的vscode就可以进行设置。直接点击编辑器右下角的LF或者CRLF,出现如下图所示的设置,直接选择即可。在设置完成之后,在敲回车键,保存在文件中的换行符就是你设置的(CRLF或者是LF,设置什么就是什么)。
Git为了解决上面提出的问题,会自动对换行符进行转换。转换的方案有3种:
可以发现,如果不使用第3种方案,那么在Git仓库(包括本地仓库和GitHub远程仓库)中保存的文件的换行符都是LF表示的。
我们自己在开发过程中,是可以修改/设置Git的换行符转换方案的。修改/设置的方法有2种。
设置autoclf属性,在控制台直接运行如下的一条命令就可以设置了:
// 提交时转换为LF,检出时转换为CRLF
git config --global core.autocrlf true
// 提交时转换为LF,检出时不转换
git config --global core.autocrlf input
// 提交检出均不转换
git config --global core.autocrlf false
上述命令运行之后,会修改.gitconfig文件。
一般在项目中,为了避免项目中同时出现CRLF和LF,还可以开启safecrlf检查。当然,如果你的项目自己定义了语法检查规则,例如使用eslint去约束换行符必须是LF,那么当你的文件中出现CRLF的时候,eslint会给你错误提示信息,告诉你不能包含CRLF,这时候,不开启safecrlf也是可以的 (一般建议开启)。
开启方法如下第一条命令:
// 拒绝提交包含混合换行符的文件 (一般设置为true)
git config --global core.safecrlf true
// 允许提交包含混合换行符的文件
git config --global core.safecrlf false
// 提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn
上述命令运行之后,也会修改.gitconfig文件。
参考:https://git-scm.com/docs/gitattributes
注意.gitattributes是针对一个单一的仓库的,也就是说每一个代码仓库都可以包含一个.gitattributes文件。
core.autocrlf 的配置依赖于每一位参与项目的开发机器上的配置,这很难确保每个人都能正确配置。于是在规范项目中的换行符方面,还有一套添加配置文件的方案。在项目的根目录下可以添加一个.gitattributes 文件。它的优先级高于core.autocrlf的设置,可以覆盖core.autocrlf的。它类似于 .gitignore 文件,随提交修改生效,一个项目中可以维持一份相同的配置。所以,它能够避免每个开发人员配置不同的问题。
对于通过.gitattributes设置换行符的转换方案,可以使用如下的命令:
1. text=auto:采用git认为最好的方式来处理文件,未在.gitattributes中
设置的项默认按照这种方式处理;(If Git decides that the content
is text, its line endings are converted to LF on checkin.
When the file has been committed with CRLF, no conversion
is done.)git发现是文本文件,那么在checkin的时候,会将文件结尾符转
换为LF。果文件已经被已CRLF的形式提交(就是说已经在Gti仓库中的文件,如
果结束符是CRLF,不会有任何的转换),不会有任何转换。
2. -text 表示让git在checkin以及checkout的时候,对end-of-line不
做任何转换。
3. text 表示在checkin的时候会被转换为LF(在repository中的文件结束
符是LF),如果需要控制在checkout的时候的换行符,需要结合eol进行设置
(也就是 控制working tree中的文件的结尾符,需要通过eol设置)。
text=auto和text的区别在于,text=auto由git来确定是不是文本文件,
从而进行转换;而text表示,你确定这个path就是文本文件,会直接对这个
path进行转换,而不是有git来decides是否转换。
4. 如果没有指定text,git会使用全局配置中的core.autocrlf来进行eol
的转换。core.autocrlf需要自己在自己的电脑上进行配置。
5. eol=crlf:此设置强制Git在checkin时对此文件的行尾标准化为LF,并在checkout文件时将其转换为CRLF。
6. eol=lf:此设置强制Git在checkin时将行尾标准化为LF,
并在checkout文件时阻止转换为CRLF(如果是LF,阻止其转换为CRLF;如果
已经是CRLF,是不会进行转换的)。
7. binary: 告诉git该文件为二进制,防止git修改该文件。git不会对对其中的换行符进行改变。等加于-text -diff,和字符编码work-tree-encoding没关系(binary不会影响文件编码)
https://stackoverflow.com/questions/33085428/gitattributes-and-the-binary-option
注意:.gitattributes文件必须要提交之后才能生效。
eol=lf与eol=crlf的区别:
标准化: 指在提交代码到git数据库(本地库) 中将文本文件中的换行符CRLF转为LF的过程
转换: 指在检出Git数据库代码过程中将文本文件中的换行符LF转换为CRLF的过程
eol=lf: 标准化 + 不转换
eol=crlf 标准化 + 转换
参考博客: