令人困擾的git autocrlf
跨平台的git repo換行問題應該可以列入「每個工程師都會踩到的十大問題」之一。整理一下自己的筆記。
設定範圍
- 在任何地方下
git config --global core.autocrlf
會影響到所有專案 - 在repo內下
git config core.autocrlf
只會影響到當前的repo
和WSL無關
不論是在windows的cmd與在WSL下git command, 基本上對autocrlf完全沒有影響。這兩種環境差異是在WSL建立檔案的時候預設會用linux line ending, cmd建立檔案是用windows line ending。
了解git的normalize
git的發明人是鼎鼎大名恨透windows的Linuz, 因此git文件中所謂的normalize, 意思是把index內的檔案的line ending轉化成unit style.
以Linux為中心思考autocrlf
思考git autocrlf的時候,最重要的事情是以Linux為中心去思考。
-
git config core.autocrlf false
預設值false, 就是原本檔案是什麼line ending commit時就照存進去index內。如果你只在linux上使用完全沒有問題,但如果你的git repo是跨平台開發,就會發生有人commit windows style有人commit linux style,你checkout出來的檔案就會照原本commit進去的line ending,因此就會發生混亂。所以有人會建議,不管你是哪個平台的用戶,剛裝完git要改掉這個預設值
-
git config core.autocrlf true
commit進去的時候幫你轉成LF, checkout出來的時候幫你轉成CRLF,所以叫做auto crlf, 通常在windows上會套用此設定, WSL與cmd通通用同一個沒有問題。在linux環境套用這個就是自找麻煩。 -
git config core.autocrlf input
commit進去的時候幫你把輸入normalize(轉成LF),checkout出來的時候原封不動, 如果你是用linux環境, 用這個設定沒啥問題, 還可以避免不小心把crlf commit進去repo。windows用這個設定就是自尋煩惱,commit進去還是crlf結果checkout出來就變成lf, 不是自己找麻煩嗎?
如果專案已經一段時間
如果專案已經發生Unix style和Windows style的line ending混雜在一起的情況,建議會是照著git的設計走
- index中的檔案都以unit style為基準,checkout出來時根據平台決定要不要crlf, windows環境就用autocrlf = true, linux環境就用input
- 可以下
git add --renormalize .
git會協助把index中的crlf轉成lf,讓你再commit一次。 - 如果檔案實在太多,原本大家都把crlf全部commit進repo,而且repo只有windows使用,那全部都用autocrlf=false也無妨,只是在用WSL開發的時候要注意不要把line ending是LF的再commit進去。
- 用.gitattributes去規範是更強硬的作法,那應該是另一篇文章了
gotcha
commit的時候檔案不會改變line ending
只有重新從repo中checkout出來時才會,你可以rm該檔案再checkout回來看看
令人困惑的錯誤訊息
在windows上設定成autocrlf = true, 有時候git add Line ending是LF的檔案,會跳出 warning: LF will be replaced by CRLF.
的訊息,這是個令人困惑的訊息,你會想說明明就是把CRLF轉成LF並存起來,到底為什麼要把他換成CRLF?
可以參考stackoverflow Windows git “warning: LF will be replaced by CRLF”, is that warning tail backward?
這個錯誤訊息你可以想成,他其實是git add時會去trigger CRLF檢查,如果是LF,再下次checkout時要轉成CRLF,所以就跳這個訊息。無視就可以了。關於此問題的原因可以參考官方文件 https://git-scm.com/docs/gitattributes 中的節錄
git add itself does not touch the files in the work tree, the next checkout would, so the safety triggers;