通常來說發生這種情況就是檔案的斷行跑掉了,如果沒有好好解決到時候log會常常出現修改,但是實際上並不是真的修改,未來查找log很辛苦。
在這篇將會對於如何一勞永逸處理掉這個斷行問題做個說明。
問題描述
有時候檢查檔案狀態,發現有變更,但是實際比對會發現其實什麼變更都沒有:
當然,如果各位有在每次commit的時候認真比對的話,那麼一定不會把這個加到commit裡面,但是有時候如果漏看的話,不小心把這個commit上去, 只會造成未來在看的時候有更多雜訊,浪費時間。
解決方式
首先要設定好讓git自動做斷行處理,再來如果專案裡面以前沒有設定過,很有可能斷行已經亂掉,這時候做一個一致化(Normalize line ending)的動作。
設定
要一次解決這個問題,可以透過兩個設定:
- git config --global core.autocrlf
如果是windows設定為
true
git config --global core.autocrlf true
如果是Unix系列設定為
input
git config --global core.autocrlf input
- 為專案加入
.gitattributes
檔案 檔案裡面要加入
* text=auto
更多gitattribute關於斷行的設定可以參考這個github repo 一些不同語言的gitattributes範本
或者可以看我自己每一個專案都會放的gitattribute檔案:我的gitattribute
一致化
做好了以上設定,要把現行的斷行一致化就變得很簡單,只需要:
- 假設有任何修改尚未commit,先commit
git commit -am "儲存目前修改"
- 把所有檔案刪掉(不包含.git)
git rm --cached -r .
- 重新從repo把刪除的修改revert掉
git reset .
- 加入index
git add -u
- 如果有看到很多warning提示會從crlf轉成lf是正常的。- commit上去
git commit -m "斷行一致化處理"
如果對於這兩個設定的目的和用途為何,請繼續往下看。
問題發生的原因
Windows 和 Unix(包含Linux和mac)代表斷行的字符是不一樣的。
- Windows
crlf
- 兩個字符代表斷行- Unix
lf
- 字符代表斷行
還記得git是版控檔案內容,所以假設本來是crlf
,如果被改成了lf
那麼對於git來說就是一個修改。
但是因為斷行字符是看不到的內容,所以有些比對工具不會顯示出任何差異,造成混亂。
而本質上這些不應該算是修改,而是因為作業系統不同而導致的問題,所以git本身有考慮進去怎麼處理。
要解決這個問題其實很簡單,假設不管哪個作業系統都是用一樣的斷行作為儲存,那麼就不會有因為斷行不一樣的原因出現修改。
假設一開始沒有設定好,那麼很有可能有些檔案存成lf有些存成crlf,這個時候就需要做斷行一致化的動作(normalize line ending)
git 如何處理這個問題 - 自動轉換的時間點
在git裡面,其實內建的時候就有考慮到這個事情,所以他有允許做自動轉換。
這個自動轉換發生在兩個時間點:
- 當把檔案寫到repo的時候
- 發生的時間點如:
git add
、git commit
- 當把檔案從repo讀出來的時候
- 發生的時間點如:
git checkout
所以我們可以透過設定告訴git在這兩個時間點的時候,應該要怎麼轉換。
git 斷行自動轉換相關設定
在git裡面有兩個設定是告訴git如何做這個斷行轉換:
- git config 的
core.autocrlf
.gitattributes
設定
這邊git config的設定對所有專案都有作用,但是只能夠對自己有起作用,換句話說如果在團隊裡面,有些人的電腦沒有設定好 那麼只靠這個設定是不夠的,因為很有可能就是有個別的電腦設定有問題導致斷行錯亂。
因此,.gitattributes
的作用就出來了,這個是能夠跟著專案走的斷行處理設定,設定了就不用擔心有個別電腦沒有設定 core.autocrlf
的問題。
git config core.autocrlf
這個其實就是在設定讀和寫的時候自動轉換斷行的處理,總共有三個設定:
- auto
- input
- false
這三個設定分別為:
讀的時候轉換 | 寫的時候轉換 | 建議 | |
---|---|---|---|
auto | lf 轉 crlf | crlf 轉 lf | Windows作業系統使用 |
input | 不轉換 | crlf 轉 lf | Unix作業系統使用 |
false | 不轉換 | 不轉換 | 不建議使用 |
.gitattributes
這個檔案放在同.git
資料夾層級,裡面可以設定一些檔案屬性,其中一個就是轉換的部分
一個範例檔案可能長成如下:
* text=auto *.md text *.csproj text eol=crlf
自動轉換的設定是* text=auto
- 這個意思是只要是text類型的檔案git會自動轉換(類似於core.autocrlf但是更加智能)。
這個時候可能會好奇,到底哪些是屬於text檔案?git會自動判斷,不過也可以透過設定強制告訴git,例如:*.md text
就是說md結尾的都是 屬於text類型 - 換句話說就是會做轉換斷行的處理。
也有可能有些檔案要保持某一個斷行,例如*.csrpoj
(C# 專案檔案,要保持crlf),這個時候也可以透過設定:*.csproj text eol=crlf
如果想參考一些不同檔案的設定,可以參考這個repo: 一些不同語言的gitattributes範本
我自己也有一個常用的設定,也可以參考一下:我的gitattribute
結語
斷行的部分其實還有幾個相關設定,不過那些設定基本上不會碰到,因此我就沒有提。
希望透過這篇也讓大家了解到斷行在不同作業系統會帶來的問題,並且怎麼樣能夠一勞永逸的解決。
gitattributes其實還有別的進階用途,未來有機會在和大家介紹
參考資料
- Mind the End of Your Line(英文)
- 一篇很詳細介紹關於斷行問題的文章
- gitattributes的官方說明(英文)
- 介紹整個gitattributes的其他應用
- github介紹一致化斷行的處理(英文)
沒有留言 :
張貼留言