﻿# Git 在 Windows 平台處理斷行字元 (CRLF) 的注意事項

在 Windows 平台使用 Git 時，偶爾會遇到斷行字元的問題，之前遇到時並不知道為什麼會這樣，只覺得怪怪的，最近終於釐清這個問題，所以決定撰文解釋一下來龍去脈，以免有人還遇到相同的問題。

因為 Git 版本控管早期是為了維護龐大的 Linux kernel 而設計而成的，所以絕大部分的使用環境都是 Linux 平台，而在 Linux 平台下，文字檔案的斷行符號預設為 LF 字元 ( \\n ) ( 0x0A )。不過，在 Windows 環境下，文字檔案的預設斷行符號卻是 CRLF ( \\r\\n ) ( 0x0D 0x0A )，比 Linux 多了一個字元。也就是說，如果你的軟體專案的原始碼總共有 100 萬行，這代表你如果用 CRLF 來儲存斷行字元，會多浪費 100 萬個位元組來儲存這些多餘的 CR ( \\r ) 字元。因此，在使用 Git 工具的時候，通常建議你將 LF 當成文字檔案的斷行符號。

在 Windows 平台使用 Git 版本控管，[Git for Windows](http://git-scm.com/download/win) 是一套必備工具，在安裝的時候，有個步驟是 **Configuring the line ending conversions** 這項，通常我們會選擇第一個選項，也就是 **Checkout Windows-style, commit Unix-style line endings** 選項。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/855d419ba0377586ff82-image_2286.png)

這個選項會讓 git 指令在執行的時候，自動轉換斷行符號，從哪裡轉換呢？就是從 **Git 版本庫中的檔案**與 **Git 工作目錄中的檔案**自動轉換斷行符號。簡單來說，就是【當執行 git add 命令時，文字檔案中出現的 CRLF 斷行字元會自動被轉換成 LF 字元。而利用 git checkout 取出檔案到**工作目錄**時，則會自動將 LF 字元，轉換成 CRLF 字元】，這是一個自動轉換的程序，git 工具會自動幫你完成這些轉換，所以你幾乎不需要知道有這種設定存在。

如果你忘記在安裝時到底設定了哪一組，可以用以下指令進行查詢：

```
git config core.autocrlf
```

若回傳的結果不是 **true** 的話，可以用以下指令進行修改：( 通常 **core.autocrlf** 都設定在**系統層級** )

```
git config --system core.autocrlf true
```

當然，如果你要設定在**使用者層級**也是可以的，如下指令：

```
git config --global core.autocrlf true
```

 ![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/fea49fcfd15769269272-image_2287.png)

我前陣子在 GitHub 上曾經發現過一個 [Landscaping With Frontend Development Tools](https://github.com/codylindley/frontend-tools) 專案，這裡收集了上百個前端開發工具的大收集，索性直接翻譯成正體中文版，並取名為 [各式 Web 前端開發工具整理](https://github.com/doggy8088/frontend-tools)。如果你想從 GitHub 直接將我的翻譯專案 **複製** (clone) 回去，可以使用以下指令：

```
git clone https://github.com/doggy8088/frontend-tools.git
```

不過，詭異的是，我將專案複製回來後，在沒有進行任何修改的情況下，竟然檔案會有被修改過的跡象！

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6f9e8073beb9eeb6f9ff-image_2288.png)

各位不覺得奇怪嗎？我第一次遇到的時候，只覺得 Git 怎麼怪怪的？是不是 [Git for Windows](http://git-scm.com/download/win) 有 Bug 呢？

後來發現到，因為專案我是從 [frontend-tools](https://github.com/codylindley/frontend-tools) 給 fork 過來的，原本的專案就有一個 [.gitAttributes](https://github.com/codylindley/frontend-tools/blob/master/.gitAttributes) 檔案，裡面定義了所有文字檔案都應該要自動轉換斷行符號，也就是要對文字格式進行 **正規化** (normalize) 的意思： ( 該檔案的格式說明請參見 [Git - Git Attributes](https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes) )

```
* text=auto
```

也因為 **.gitAttributes** 檔案的存在，導致了 Git 在取出檔案的同時，也希望幫你把所有專案內的文字檔案進行正規化。

**註**: 因為執行 git clone 時會隱含執行 git checkout 命令，如此一來你的工作目錄才有檔案！

重點就在於，以前我不知道要轉換甚麼，這個取出檔案的過程 git 幫我改了些甚麼？還是有其他原因？

現在，我終於知道了，首先我先取出在 **目前最新版** ( HEAD ) 的 README.md 檔案，使用以下指令：

```
git show master:README.md > README.HEAD.md
```

然後比對了一下 git 幫我取出的 **README.md** 檔案，結果發現：兩個檔案一模一樣，完全沒有轉換，但執行 git status 指令時，它卻告訴我檔案被修改了！

後來才發現到 GitHub 上的 [Dealing with line endings](https://help.github.com/articles/dealing-with-line-endings) 文件，這才真相大白，原來事實的真相是：

因為 .gitAttributes 檔案定義了要對所有文字檔案進行正規化處理，所以儲存在版本庫中檔案內容必須以 LF 結尾，在工作目錄中的文字檔案必須以 CRLF 結尾，這就是「正規化」要做的事。而我們雖然工作目錄中的檔案是 CRLF 結尾，但版本庫中的檔案卻也是以 CRLF 結尾，那就不對了！

所以，他就是要讓你重新再 commit 一個版本，好讓 git 幫你完成正規化的程序，讓儲存在版本庫中的檔案改用 LF 當成文字檔案的斷行符號。

我們重新複製這個專案，然後修正字元，你可以參考以下指令執行的圖示：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a5c9341f88c5c613a6f8-image_2289.png)

我們要如何驗證這個過程真的有做到正規化的結果呢？請輸入以下指令取出目前版本庫中的 README.md 檔案，我們把檔案匯出到 test.txt 檔案中：

```
git show master:README.md > test.txt
```

最後再以 [Notepad2](http://www.flos-freeware.ch/notepad2.html) 開啟該檔案，從右下角某一格可以看出該檔案的斷行符號為何，如果是 LF 的話，就代表正規化執行成功：

如下圖示：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/550f67708ff3325bd83c-image_2290.png)

**心得分享**

我一直都認為，在學習工具或技術的過程中，只要感覺到有「怪怪的」，基本上就是自己不夠了解他，當然也有可能是工具本身的 Bug，這些還是能夠透過一些方法進行驗證，最重要的還是對一套工具或一門技術的「核心觀念」是否真正理解，當掌握了來龍去脈，解題的方向自然會更加正確，也更容易找到解答。

我最近將 O’REILLY 的「 [版本控制使用 Git (第二版)](http://www.books.com.tw/products/0010574090) 」這本書給看完，當中學習到許多紮實的觀念，雖然中文翻譯的品質不太理想 (書中的專有名詞很少中英對照，導致看中文時不知道英文的原意為何，這會導致一定程度的閱讀障礙)，但在中、英文版交互閱讀之下，閱讀的品質還是可以漸入佳境，最終吸收到較為完整的知識，整體上來說，還是推薦各位可以閱讀這本書！

建議繼續閱讀【[Visual Studio Tools for Git 處理斷行字元 (CRLF) 的注意事項](/post/2014/02/20/Visual-Studio-Tools-for-Git-Line-Ending-Conversion-Notes.aspx)】一文。

**相關連結**

-   [Dealing with line endings · GitHub Help](https://help.github.com/articles/dealing-with-line-endings) ( Windows )
-   [7.2 Customizing Git - Git Attributes](https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes)
-   [.gitattributes man page](http://git-scm.com/docs/gitattributes#_checking-out_and_checking-in)
-   [git-config man page](http://git-scm.com/docs/git-config)
-   [Progit: Getting Started - First-Time Git Setup](http://git-scm.com/book/en/Getting-Started-First-Time-Git-Setup)
-   [Mind the End of Your Line](https://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/) - The full story of line endings in Git *by Tim Clem*
