最近工作使用 sourceTree
的時候經常發現,儘管只是很小的程式碼改動,但是在檔案 diff 的區域莫名的多了很多空格,即使選擇忽略空格,一項項提交仍有很大機率報錯,很是煩惱。最初的想法是通過指令碼去除掉空格,但經過一番努力依然沒有徹底解決問題。
偶然的,通過對同事提交的檔案使用命令列執行diff的時候,發現存在大量的 ^M
符號,考慮到同事使用的是 windows 系統,終於意識到很有可能是換行符的問題。經過排查終於發現在 sublime 中設定了 line Endings 為 windows (CRLF),而作為主力開發的 IDEA 設定為 LF。最終導致了專案換行符混亂。剩餘內容為著力於解決問題。
背景
首先在不同作業系統中,換行符並不統一,Linux 系統中使用 0x0A(LF)
, windows 系統中使用 0x0D0A(CRLF)
, 而 MAC OS 系統起初使用0x0D(CR)
後來和 Linux 系統保持一致。而 git 預設採用 Linux 的換行符(當然這一點並不奇怪)。
git 為了解決不同平臺換行符不一致的問題,在 windows 作業系統中預設在檢出程式碼時將 LF 轉換為 CRLF,而在提交的時候再轉換為 LF,但是看似完美的解決方案在中文環境中卻失效了。
解決方案
設定 git 全域性引數
git 中有三個引數於換行符有關:
eol
: 設定工作目錄中檔案的換行符,有三個值 lf, crlf 和 native(預設,同作業系統)autocrlf
:true
表示檢出是轉換CRLF, 提交時轉換為 LFinput
表示檢出是不轉換,提交時轉換為 LFfalse
表示不做轉換
safecrlf
:true
表示不允許提交時包含不同換行符warn
則只在有不同換行符時警告false
則允許提價時有不同換行符存在
配置方法:
<!--統一換行符為 lf-->
git config --global core.eol lf
<!--將自動轉換關閉,避免轉換失敗不能不同進行提交-->
git config --global core.autocrlf false
<!--禁止混用 lf 和 crlf 兩種換行符-->
git config --global core.safecrlf true
複製程式碼
增加配置檔案 .gitattributes
雖然通過設定了 git 全域性引數解決了問題,但是作為團隊協作的話,並不能保證所有人都正確配好了。git 提供了.gitattributes檔案解決了這個問題。在專案根目錄新建.gitattributes檔案,新增一下內容:
# Set the default behavior, in case people don't have core.autocrlf set.
* text eol=lf
複製程式碼
通過這種方式避免有人沒有設定 core.autocrlf 引數,並且將該檔案加入版本控制中。
另外根據需要 .gitattributes 檔案可以在專案不同目錄中建立,而一些非文字檔案可以設定為二進位制檔案,不用考慮換行符問題。
專案已有內容轉換換行符
對於專案已有內容如何進行轉換呢,推薦使用dos2unix
工具,在mac中可以很方便的使用brew安裝,而windows系統中git bash也自帶了該工具。
以轉換專案中 java 原始碼為例:
cd <project_path>
find . -type file -name '*.java' -exec dos2unix {} +
複製程式碼
最後使用編輯器的時候也確保換行符設定正確