在Git或者Github上进行跨平台项目合作开发时,会遇到换行符转换的问题。
编辑文档的过程中,在按下回车键的时候实际上是向文档插入了一个不可见的换行符。在Windows系统中是CRLF
(Carriage-Return Line-Feed,即回车换行)就是回车符CR
(ASCII 13, \r
)加上换行符LF
(ASCII 10, \n
)。在Linux/UNIX、OS X系统中只用换行符LF
来标识一行的结束。
问题就来了,结尾换行符不一致在版本更新的时候就会导致不必要的麻烦,版本管理系统可能将换行符不一致视为对文件的修改。这当然不是我们所希望的,所幸,Git和Github有专门针对这个问题的解决方法。
Global settings for line endings
git config core.autocrlf
命令可以管理换行符的识别,详细说明可以参考Git的帮助文档。在Windows系统上,只要将该项设置为true
就可以了。
$ git config --global core.autocrlf true
# Configure Git on Windows to properly handle line endings
在Linux/UNIX、OS X系统上将该项设置为input
。
$ git config --global core.autocrlf input
# Configure Git on OS X or Linux to properly handle line endings
此时,Git会在Windows系统提交代码时将换行符转换成LF
,checkout时转换为CRLF
;在Linux/UNIX、OS X系统以及库中保留LF
作为换行符。
如果你是Windows程序员,且正在开发仅运行在Windows上的项目,可以设置false
取消此功能,把回车符记录在库中:
$ git config --global core.autocrlf false
Per-repository settings
当然,并非所有现实情况都那么完美,我就遇到了Stack Overflow这个帖子上面的问题。我使用的操作系统是Windows,但是开发的项目需要在不能连接外网的CentOS虚拟机中运行,多是Python、Shell脚本。在Linux/UNIX系统中,Windows的换行符会被当作特殊字符处理,可能会影响程序运行并报错。
附上处理该类问题的一点经验:
对于逻辑没有问题但运行一直报错的程序可用
vi -b
查看源文件,看每行末尾是否有粗体^M
字符。如果有就说明是换行符在作怪,可用1, $ s/^M//g
命令进行替换。其中,^M
字符需按ctrl
+v
+m
组合键输入。
此时问题就来了,如果直接设置core.autocrlf
为true
的话,在签出时会将其自动转换成CRLF
换行符,在提交代码时会报warning: LF will be replaced by CRLF
。该警告一般是项目中出现了CRLF
和LF
换行符混用的情况,LF
在提交时会被自动转换成CRLF
。对于Windows和UNIX混用的情况显然全局的设置就不太合适了,需要针对该项目设置具体换行符。
建立一个.gitattributes文件,每一行开始是文件名的pattern,即具体的文件类型,空格后是指定具体使用的换行符。下面是我在官方例子中加入了.sh脚本文件的换行符指定,这样就会更明确每个设置项的意义。
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
# Declare files that will always have LF line endings on checkout.
*.sh text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
在处理这类Windows和UNIX混用的项目时要更加小心,建议使用专门的文本编辑器来打开此类文件,并且在IDE或者文本编辑器统一设置换行符为LF
以及编辑环境为UNIX。
Refreshing a repository after changing line endings
当设置了core.autocrlf
选项或者添加了.gitattributes以后,可以提交编辑后的源文件。此时,Git会帮助你转换每个文件中的换行符。
最好按照Github帮助文档配置并备份文件。首先要删除除.git文件夹外的所有文件,然后重建文件。
保存当文件,保证所发生的修改不丢失。
$ git add . -u $ git commit -m "Saving files before refreshing line endings"
删除Git本地库的索引
$ git rm --cached -r .
重写Git本地库索引确认新的换行符
$ git reset --hard
将所有文件重新添加,准备提交。这时也是一个机会检查哪些文件的换行符还有问题,屏幕会输出提示。
$ git add . # It is perfectly safe to see a lot of messages here that read # "warning: CRLF will be replaced by LF in file."
提交代码。
$ git commit -m "Normalize all the line endings"
Conclusion
网上有一些方法很暴力,直接将.git文件夹删除后重新建库,把core.autocrlf
设置为false
也没有说明为什么。所以还是需要搞清楚原理根据项目的情况来设置:
一般情况下建议Windows用户将
core.autocrlf
设置为true
,UNIX用户将core.autocrlf
设置为input
。如果有Windows和UNIX系统混用的项目时,针对该项目确认IDE以及文本编辑器的换行符设置和每种文件类型的换行符,并添加.gitattributes文件。
不太建议把
core.autocrlf
设置为false
即使你的项目是纯Windows项目。我是小心谨慎的性格,人生总有太多难免嘛