在你通過github或者其他遠(yuǎn)程托管服務(wù)器來和其他人進(jìn)行協(xié)同開發(fā)代碼的時(shí)候,確保換行符被正確處理是一項(xiàng)很重要的事。首先,你需要知道不同的操作系統(tǒng)對(duì)換行符的定義會(huì)有所不同,Unix或類Unix操作系統(tǒng)的換行符叫做LF,而windows系統(tǒng)的叫做CRLF,二者具有很大的區(qū)別:
Unix系統(tǒng)里,每行結(jié)尾只有“<換行>”,即"n";Windows系統(tǒng)里面,每行結(jié)尾是“<換行><回車>”
Note:引自回車(CR)與換行(LF), 'r'和'n'的區(qū)別.
這就是造成問題的根源——即如果你使用的是windows系統(tǒng),而你的小伙伴用的是Mac的話,當(dāng)你們使用git協(xié)同開發(fā)軟件時(shí),就會(huì)出現(xiàn)換行符不統(tǒng)一的問題。
git其實(shí)可以自己處理換行符不統(tǒng)一的問題,但是可能會(huì)產(chǎn)生意想不到的結(jié)果。因此,有必要進(jìn)行相關(guān)的配置,我們通常有兩種方案:
- 全局配置換行符
- 針對(duì)某個(gè)倉庫的局部配置
換行符的全局配置
一般如果你不想麻煩的話,可以采用比較簡單的方法,如下所示:
$ git config --global core.autocrlf true
其實(shí),在你安裝windows版本的git或者torgoiseGit時(shí),你可能已經(jīng)進(jìn)行過這樣的配置,也許你當(dāng)時(shí)并未知道那個(gè)選項(xiàng)是什么意思。下面這張圖是不是有些眼熟呢?

Note:本圖片來自百度經(jīng)驗(yàn):http://jingyan.baidu.com/article/9f7e7ec0b17cac6f2815548d.html。
不過,也許很多人安裝git的時(shí)候,是一直next...next吧!其實(shí)上面寫得很清楚:
- Checkout Windows-style, commit Unix-style line endings
當(dāng)檢出文本文件時(shí),Git會(huì)將LF轉(zhuǎn)換為CRLF。當(dāng)提交文本文件時(shí),CRLF將會(huì)被轉(zhuǎn)換為LF。對(duì)于跨平臺(tái)的項(xiàng)目,這是對(duì)Windows系統(tǒng)的推薦設(shè)置。("core.autocrlf" is set to "true")
- Checkout as-is, commit Unix-style line endings
當(dāng)檢出文本文件時(shí),Git不會(huì)做任何轉(zhuǎn)換。當(dāng)提交文本文件時(shí),CRLF將會(huì)被轉(zhuǎn)換為LF。對(duì)于跨平臺(tái)的項(xiàng)目,這是對(duì)Unix系統(tǒng)的推薦設(shè)置。("core.autocrlf" is set to "input")
- Checkout as-is, commit as-is
不論是檢出還是提交文本文件時(shí),Git都不會(huì)做任何轉(zhuǎn)換。對(duì)于跨平臺(tái)的項(xiàng)目,不推薦采用該選項(xiàng)。
顯然,第一個(gè)選項(xiàng)就是我們所介紹的第一種方法。
順便吐槽一下,我在網(wǎng)上看到很多介紹如何安裝Git的博客,很少有詳細(xì)說明每一個(gè)安裝步驟的,有些甚至直接說
一直next下去就安裝完成了。
一方面原因就是他們也不知道,其實(shí)這樣可能會(huì)對(duì)新手產(chǎn)生誤導(dǎo),而且未免有些不負(fù)責(zé)任。
單一倉庫的換行符局部配置
當(dāng)然,有更好的方法解決換行符不統(tǒng)一的問題——使用.gitattributes文件統(tǒng)一換行符。這種方法是針對(duì)某個(gè)倉庫進(jìn)行換行符的統(tǒng)一配置,即時(shí)你已經(jīng)進(jìn)行了全局配置。
另外,這個(gè)文件有點(diǎn)兒類似于.gitignore,不僅名字很類似,使用方式,編寫語法也很像。這個(gè)文件必須位于倉庫的根目錄,可以像其他文件一樣進(jìn)行修改、提交。下面介紹如何編寫這個(gè)文件:
文件內(nèi)容看起來像一張表格,總共分為兩列:左邊一列是git要匹配的文件名;右邊是git需要采用的換行符格式。下面我們來看一個(gè)栗子:
# 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
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
如果你熟悉.gitignore的話,你會(huì)覺得上面這個(gè)文件的左邊一列很熟悉,這里我們就不再贅述了,不熟悉的話,請(qǐng)自行查閱相關(guān)資料。唯一的不同就是.gitattributes文件多了右邊一列,如text, text eol=crlf, binary,剛剛我們也說過這一列是用來設(shè)置左邊對(duì)應(yīng)文件使用的換行符格式的,左右兩列用空格隔開。下面我們來詳細(xì)介紹下右邊一列的語法:
text=auto
讓git自行處理左邊匹配的文件使用何種換行符格式,這是默認(rèn)選項(xiàng)。text eol=crlf
對(duì)左邊匹配的文件統(tǒng)一使用CRLF換行符格式,如果有文件中出現(xiàn)LF將會(huì)轉(zhuǎn)換成CRLF。text eol=lf
對(duì)左邊匹配的文件統(tǒng)一使用LF換行符格式,如果有文件中出現(xiàn)CRLF將會(huì)轉(zhuǎn)換成LF。binary
告訴git這不是文本文件,不應(yīng)該對(duì)其中的換行符進(jìn)行改變。另外,binary和符號(hào)-text -diff是等價(jià)的。
上面這些語法應(yīng)該已經(jīng)足夠了,如果有興趣的,可以自行查閱相關(guān)資料,比如官方的資料:https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes。
如果創(chuàng)建倉庫之前沒有進(jìn)行換行符配置怎么辦
也許你在看完我的博客之后,才意識(shí)到自己并未進(jìn)行相關(guān)的設(shè)置抑或是你想修改換行符配置,于是你興致勃勃地按照我的博客進(jìn)行了配置,結(jié)果你發(fā)現(xiàn)出了一堆莫名其妙的警告或者錯(cuò)誤。
怪我嘍?

不要著急吐槽,兵來將擋,水來土掩,沒有解決不了的問題!
- 首先保存Git中目前的所有文件,這樣可以確保你的工作不會(huì)丟失。
# 在倉庫的根目錄下運(yùn)行命令
$ git add . -u
$ git commit -m "Saving files before refreshing line endings"
- 然后刪除暫存區(qū)中的所有文件,
$ git rm --cached -r .
- 重寫暫存區(qū)以重新應(yīng)用新的換行符
$ git reset --hard
- 找回所有修改過的文件并加入暫存區(qū),同時(shí),你也可以查看些文件沒有被修改。
$ git add .
# 出現(xiàn)"warning: CRLF will be replaced by LF in file."的警告是很正常的現(xiàn)象
- 提交你對(duì)倉庫的修改
$ git commit -m "Normalize all the line endings"
參考資料
Github help文檔:Dealing with line endings
Stackoverflow.com:Trying to fix line-endings with git filter-branch, but having no luck
注:本文遷移自我的CSDN博客:https://blog.csdn.net/github_30605157/article/details/56680990
。