在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项目。我是小心谨慎的性格,人生总有太多难免嘛
