通過閱讀git-config文檔理解Git如何使用autocrlf、safecrlf、eol和.gitattributes處理line-ending

[toc]

一、遇到的問題

在Windows平臺上,會出現(xiàn)如下的warning:

$ git add app.wxss
warning: LF will be replaced by CRLF in app.wxss.
The file will have its original line endings in your working directory.

為什么會出現(xiàn)這個warning呢?

二、為什么會出現(xiàn)這個問題

通過查閱《ProGit》的相關(guān)內(nèi)容,可以得知:

If you’re programming on Windows and working with people who are not (or vice-versa), you’ll probably run into line-ending issues at some point. This is because Windows uses both a carriage-return character and a linefeed character for newlines in its files, whereas Mac and Linux systems use only the linefeed character. This is a subtle but incredibly annoying fact of cross-platform work; many editors on Windows silently replace existing LF-style line endings with CRLF, or insert both line-ending characters when the user hits the enter key.
簡單翻譯一下,Windows在換行的時候,同時使用了回車符(carriage-return character)和換行符(linefeed character);而Mac和Linux系統(tǒng)(很老的mac系統(tǒng)才是CR,可以參見wiki),此時,僅僅使用了換行符(linefeed character)。同時呢,Windows的許多編輯器還悄悄滴將LF修改成了CRLF格式的行結(jié)束符,或者在你敲回車的時候,CRLF格式的行結(jié)束符就產(chǎn)生了。當(dāng)然,這一切都發(fā)生在同時存在Windows和非Windows的跨平臺工作中,如果大家都是同一種操作系統(tǒng),那么,就天下太平了。

warning中所說的LF和CRLF分別是linefeed和carriage-return&linefeed。
那么現(xiàn)在,再仔細(xì)看warning的內(nèi)容,為什么在git add的時候,“警告:app.wxss中的LF將來會被替換成CRLF”?

三、為什么LF->CRLF

Git can handle this by auto-converting CRLF line endings into LF when you add a file to the index, and vice versa when it checks out code onto your filesystem.
Git有一個針對性的功能:當(dāng)添加到暫存區(qū)時,自動將CRLF轉(zhuǎn)換成LF;反之,當(dāng)檢出時,自動將LF轉(zhuǎn)換成CRLF。
You can turn on this functionality with the core.autocrlf setting.
可以通過設(shè)置core.autocrlf來開啟這個功能。

看到這里,就更加不懂了,添加到暫存區(qū)時,為什么警告LF將被轉(zhuǎn)換成CRLF?這不是和功能相反了嗎?

四、原因

這個問題與git-config里面的相關(guān)設(shè)置有關(guān),主要涉及到三個參數(shù):

  • core.autocrlf
  • core.safecrlf
  • core.eol

這三個參數(shù)用來配置Git處理line-ending的方式。

五、接下來,來看如何配置

1. core.autocrlf

(1) true

If you’re on a Windows machine, set it to true?—?this converts LF endings into CRLF when you check out code:
$ git config --global core.autocrlf true
如果是在 Windows 系統(tǒng)上,把它設(shè)置成 true,這樣在檢出代碼時,換行(LF)會被轉(zhuǎn)換成回車和換行(CRLF)

(2) input

If you’re on a Linux or Mac system that uses LF line endings, then you don’t want Git to automatically convert them when you check out files; however, if a file with CRLF endings accidentally gets introduced, then you may want Git to fix it. You can tell Git to convert CRLF to LF on commit but not the other way around by setting core.autocrlf to input:
$ git config --global core.autocrlf input
如果使用以換行作為行結(jié)束符的 Linux 或 Mac,你不需要 Git 在檢出文件時進(jìn)行自動的轉(zhuǎn)換;然而當(dāng)一個以回車加換行作為行結(jié)束符的文件不小心被引入時,你肯定想讓 Git 修正。 你可以把 core.autocrlf 設(shè)置成 input 來告訴 Git 在提交時把回車和換行轉(zhuǎn)(CRLF)換成換行(LF),檢出時不轉(zhuǎn)換

(3) false

If you’re a Windows programmer doing a Windows-only project, then you can turn off this functionality, recording the carriage returns in the repository by setting the config value to false:

$ git config --global core.autocrlf false

如果你是 Windows 程序員,且正在開發(fā)僅運行在 Windows 上的項目,可以設(shè)置 false 取消此功能,把回車(CR)保留在版本庫中

以上,是core.autocrlf的設(shè)置規(guī)則與建議。

2. core.safecrlf

通過查閱git-scm上的文檔上關(guān)于git-config的文檔或者mirrors.edge.kernel.org

If true, makes Git check if converting CRLF is reversible when end-of-line conversion is active. Git will verify if a command modifies a file in the work tree either directly or indirectly.For example, committing a file followed by checking out the same file should yield the original file in the work tree. If this is not the case for the current setting of core.autocrlf, Git will reject the file.

簡單翻譯一下:當(dāng)core.autocrlftrue或者input時,算激活了eol,此時如果core.safecrlftrue,Git檢查crlf轉(zhuǎn)換是否正常,比如Windows平臺,core.autocrlf設(shè)置為true,如果工作區(qū)的文件中含有LF,Git就會拒絕,因為true的情況下,Git認(rèn)為工作區(qū)應(yīng)該都是CRLF才對啊

給你一個致命大禮,fatal:LF would be replaced by CRLF in app.wxss.,阻止你繼續(xù)操作。


^?_?^ 使用dos2unix進(jìn)行手動轉(zhuǎn)換

這種情況不要慌,可以使用dos2unix工具中的unix2dos將LF轉(zhuǎn)換成CRLF,來滿足core.autocrlftrue的要求。當(dāng)然,解決的方法有很多,可以根據(jù)實際情況,使用不同的方法來解決。
以下命令可以將當(dāng)前文件夾內(nèi)的文件批量的轉(zhuǎn)換,也有其他方式,比如find . -type f -exec dos2unix {} +,可以自行Google

find . -type f -print0 | xargs -0 dos2unix

dos2unix工具在Windows的MINGW64 Git Bash客戶端上自帶,在mac平臺可以Google how to install dos2unix on mac,同理linux(sudo apt-get install dos2unix),哈哈哈。


The variable can be set to "warn", in which case Git will only warn about an irreversible conversion but continue the operation.
也可以設(shè)置core.safecrlfwarn,Git就只會警告一下,不會阻止你。

繼續(xù)看文檔的內(nèi)容。寫著寫著成了《帶你看文檔系列》了,所以很多問題,仔細(xì)看文檔就能解決,但是文檔太多,也很難看懂,只能花時間多看了。

CRLF conversion bears a slight chance of corrupting data. When it is enabled, Git will convert CRLF to LF during commit and LF to CRLF during checkout. A file that contains a mixture of LF and CRLF before the commit cannot be recreated by Git. For text files this is the right thing to do: it corrects line endings such that we have only LF line endings in the repository. But for binary files that are accidentally classified as text the conversion can corrupt data.
If you recognize such corruption early you can easily fix it by setting the conversion type explicitly in .gitattributes. Right after committing you still have the original file in your work tree and this file is not yet corrupted. You can explicitly tell Git that this file is binary and Git will handle the file appropriately.

這一段主要是說,同時有LFCRLF的文件是被腐蝕的,這類文件是不被Git認(rèn)可的,而CRLF的轉(zhuǎn)換過程很可能會產(chǎn)生腐蝕的文件,比如二進(jìn)制的文件被當(dāng)作文本的話,就會被腐蝕。

所以提出了重要的文件.gitattributes來明確轉(zhuǎn)換配置,而且越早設(shè)置越好。你可以明確地指出某些文件是二進(jìn)制的,比如*.jpg,Git知道了以后,會妥善處理。

Note, this safety check does not mean that a checkout will generate a file identical to the original file for a different setting of core.eol and core.autocrlf, but only for the current one. For example, a text file with LF would be accepted with core.eol=lf and could later be checked out with core.eol=crlf, in which case the resulting file would contain CRLF, although the original file contained LF. However, in both work trees the line endings would be consistent, that is either all LF or all CRLF, but never mixed. A file with mixed line endings would be reported by the core.safecrlf mechanism.

我的理解是,A和B協(xié)同開發(fā),A設(shè)置的是core.eol=lf core.autocrlf=true,B設(shè)置的是core.eol=crlf core.autocrlf=true,那么A checkout的時候,生成lf結(jié)尾的文件,而B checkout的時候,生成crlf結(jié)尾的文件。要么都是lf,要么都是crlf安全檢查不可能允許混合出現(xiàn),如果發(fā)現(xiàn)了混合的行結(jié)束符,就會報警

3. core.eol

通過查閱git-scm上的文檔上關(guān)于git-config的文檔或者mirrors.edge.kernel.org

Sets the line ending type to use in the working directory for files that have the text property set when core.autocrlf is false. Alternatives are lf, crlf and native, which uses the platform’s native line ending. The default value is native. See gitattributes[5] for more information on end-of-line conversion.
當(dāng)core.autocrlffalse,設(shè)置行結(jié)束符的類型,可以是

  • lf
  • crlf
  • native三種,其中native是指平臺默認(rèn)的行結(jié)束符。默認(rèn)的類型是native

欲知詳情,請翻閱gitattributes[5]或者mirrors.edge.kernel.org。

六、總結(jié)一下吧

1. 不安全不保險的方式

雖然Google查詢LF will be replaced by CRLF,幾個答案會建議設(shè)置

git config --global core.autocrlf false
git config --global core.safecrlf false

比如stackoverflow,知乎,github上的bolg中的某些答案(這幾個鏈接里也是有一些干貨的),
但是,通過上面我們看文檔的過程,我們發(fā)現(xiàn)這種方式,是不保險的。很容易產(chǎn)生混合,git diff的時候,就會影響我們查看版本之間的修改。

2. 個人推薦的設(shè)置方式

(1)添加.gitattributes

首先要在項目里添加.gitattributes文件,可以參考Github help-Dealing with line endingsgitattributes[5],這是我自己的.gitattributes。

(2)safecrlf設(shè)置為true

git config --global core.safecrlf true

(3)autocrlf在不同平臺不同設(shè)置

  • Windows
git config --global core.autocrlf true
  • Mac Or Linux
git config --global core.autocrlf input

(4)eol默認(rèn)native,因為autocrlf不是false,也不起作用啊

補充

第一點 Git Setup Treat Line Endings In Text Files

Git默認(rèn)的core.autocrlf其實在安裝Git For Windows的時候,讓我們選擇了,只是安裝的時候并不會注意,就是下面這張圖:

Git treat line endings in text files

由上向下依次是true input false。

第二點 TortoiseGit settings about AutoCrlf

另外,如果使用的是TortoiseGit,要注意其中的設(shè)置:


TortoiseGit settings
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • git 使用筆記 git原理: 文件(blob)對象,樹(tree)對象,提交(commit)對象 tree對象 ...
    神刀閱讀 3,795評論 0 10
  • 良好的配置有助于提高效率,減少不必要的錯誤。把運行配置的相關(guān)內(nèi)容單拎出來放到這里,查找和更新方便。 Customi...
    michael_jia閱讀 20,830評論 1 10
  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,828評論 0 23
  • 日下成影 逆風(fēng)獨行 對月當(dāng)空 凝思頓挫 驚霎之間 人生幾何 不知方圓 如若地方 路間設(shè)坷 雖有險峻 但求華麗 如若...
    虹帆閱讀 421評論 0 8
  • 第一:在不能了解客戶的真實問題時,盡量讓客戶說話 多打聽一些問題,帶著一種好奇的心態(tài),發(fā)揮刨根問底的精神,讓客戶多...
    思念的詩閱讀 175評論 0 0