天天看點

Git中CRLF與LF的轉換

1.換行符在不同的作業系統上的表示

首先要了解的一點是,對于不同的作業系統,對于換行符的表示是不一樣的。也就是說當我們在編輯一個檔案,在鍵盤上按下Enter鍵的時候,對于不同的作業系統儲存到檔案中的換行符是不一樣的。見下表:

CR:表示回車\r
LF:表示換行\n
CRLF:表示回車換行\r\n

敲下Enter鍵,不同的作業系統儲存到檔案中的值:
Windows:使用的是CRLF ==> 即\r\n,檔案中儲存的是\r\n
Linux/Unix: 使用的是LF ==> 即\n,檔案中儲存的是\n
Mac OS: 使用的是CR ==> 即\r,檔案中儲存的是\r
Mac OS X系統:使用的是LF ==> 即\n,檔案中儲存的是\n(Mac OS X已經改成和Unix/Linx一樣使用LF)
           

問題: 既然不同的作業系統,對于換行符使用不同的表示形式,如果一個團隊在開發一個共同的項目,如果你使用的是windows系統,而你的小夥伴用的是Mac的話,當你們使用git協同開發軟體時,就會出現換行符不統一的問題。

雖然對于不同的作業系統,預設的換行符的表示方法不一樣,但是編輯器是可以設定在敲下Enter鍵的時候儲存的換行符是什麼的,比如常用的vscode就可以進行設定。直接點選編輯器右下角的LF或者CRLF,出現如下圖所示的設定,直接選擇即可。在設定完成之後,在敲Enter鍵,儲存在檔案中的換行符就是你設定的(CRLF或者是LF,設定什麼就是什麼)。

Git中CRLF與LF的轉換

2.Git會自動對換行符進行轉換

Git為了解決上面提出的問題,會自動對換行符進行轉換。轉換的方案有3種:

  1. 在送出時将CRLF轉換為LF,在拉取(檢出checkout)時将UNIX換行符(LF)替換成CRLF。(Windows系統推薦使用,我們在windows上安裝git的時候,如果一路next,預設是使用這個方案)
  2. 在送出時将CRLF轉換為LF,在拉取(檢出checkout)時不進行轉換。(Linux/Unix和Mac OS和Mac OS X推薦使用,在Unix或者類Unix作業系統上安裝git,預設使用這種方案)
  3. 不進行轉換(這種方案對于跨平台項目不推薦使用)。

可以發現,如果不使用第3種方案,那麼在Git倉庫(包括本地倉庫和GitHub遠端倉庫)中儲存的檔案的換行符都是LF表示的。

3.自己指定換行符轉換方案

我們自己在開發過程中,是可以修改/設定Git的換行符轉換方案的。修改/設定的方法有2種。

3.1 通過Git的全局配置進行修改

設定autoclf屬性,在控制台直接運作如下的一條指令就可以設定了:

// 送出時轉換為LF,檢出時轉換為CRLF
git config --global core.autocrlf true   

// 送出時轉換為LF,檢出時不轉換
git config --global core.autocrlf input   

// 送出檢出均不轉換
git config --global core.autocrlf false
           

上述指令運作之後,會修改.gitconfig檔案。

一般在項目中,為了避免項目中同時出現CRLF和LF,還可以開啟safecrlf檢查。當然,如果你的項目自己定義了文法檢查規則,例如使用eslint去限制換行符必須是LF,那麼當你的檔案中出現CRLF的時候,eslint會給你錯誤提示資訊,告訴你不能包含CRLF,這時候,不開啟safecrlf也是可以的 (一般建議開啟)。

開啟方法如下第一條指令:

// 拒絕送出包含混合換行符的檔案 (一般設定為true)
git config --global core.safecrlf true   

// 允許送出包含混合換行符的檔案
git config --global core.safecrlf false   

// 送出包含混合換行符的檔案時給出警告
git config --global core.safecrlf warn
           

上述指令運作之後,也會修改.gitconfig檔案。

3.2 通過.gitattributes進行修改

參考:https://git-scm.com/docs/gitattributes

注意.gitattributes是針對一個單一的倉庫的,也就是說每一個代碼倉庫都可以包含一個.gitattributes檔案。

core.autocrlf 的配置依賴于每一位參與項目的開發機器上的配置,這很難確定每個人都能正确配置。于是在規範項目中的換行符方面,還有一套添加配置檔案的方案。在項目的根目錄下可以添加一個.gitattributes 檔案。它的優先級高于core.autocrlf的設定,可以覆寫core.autocrlf的。它類似于 .gitignore 檔案,随送出修改生效,一個項目中可以維持一份相同的配置。是以,它能夠避免每個開發人員配置不同的問題。

對于通過.gitattributes設定換行符的轉換方案,可以使用如下的指令:

1. text=auto:采用git認為最好的方式來處理檔案,未在.gitattributes中
 設定的項預設按照這種方式處理;(If Git decides that the content
 is text, its line endings are converted to LF on checkin.
 When the file has been committed with CRLF, no conversion 
 is done.)git發現是文本檔案,那麼在checkin的時候,會将檔案結尾符轉
 換為LF。果檔案已經被已CRLF的形式送出(就是說已經在Gti倉庫中的檔案,如
 果結束符是CRLF,不會有任何的轉換),不會有任何轉換。
 
 2. -text 表示讓git在checkin以及checkout的時候,對end-of-line不
 做任何轉換。
 
 3. text 表示在checkin的時候會被轉換為LF(在repository中的檔案結束
 符是LF),如果需要控制在checkout的時候的換行符,需要結合eol進行設定
 (也就是  控制working tree中的檔案的結尾符,需要通過eol設定)。 
 text=auto和text的差別在于,text=auto由git來确定是不是文本檔案,
 進而進行轉換;而text表示,你确定這個path就是文本檔案,會直接對這個
 path進行轉換,而不是有git來decides是否轉換。
 
 4. 如果沒有指定text,git會使用全局配置中的core.autocrlf來進行eol
 的轉換。core.autocrlf需要自己在自己的電腦上進行配置。

 5. eol=crlf:此設定強制Git在checkin時對此檔案的行尾标準化為LF,并在checkout檔案時将其轉換為CRLF。

 6. eol=lf:此設定強制Git在checkin時将行尾标準化為LF,
 并在checkout檔案時阻止轉換為CRLF(如果是LF,阻止其轉換為CRLF;如果
 已經是CRLF,是不會進行轉換的)。

 8. binary: 告訴git該檔案為二進制,防止git修改該檔案。git不會對對其中的換行符進行改變。

注意:.gitattributes檔案必須要送出之後才能生效。
           

eol=lf與eol=crlf的差別:

标準化: 指在送出代碼到git資料庫(本地庫) 中将文本檔案中的換行符CRLF轉為LF的過程

轉換: 指在檢出Git資料庫代碼過程中将文本檔案中的換行符LF轉換為CRLF的過程

eol=lf: 标準化 + 不轉換

eol=crlf 标準化 + 轉換

參考部落格:

  1. https://segmentfault.com/a/1190000013973362?utm_medium=referral&utm_source=tuicool
  2. https://www.jianshu.com/p/f13ef9e538e0
  3. https://git-scm.com/docs/gitattributes