天天看點

Git中crlf自動轉換的坑

新上手一個項目,克隆了代碼下來搭環境,一路坑。其中一個sh腳本執行不了,報IOException,java日志除了“找不到檔案或檔案夾”之外看不出任何資訊,手動運作腳本才發現是腳本編碼有問題:

Git中crlf自動轉換的坑
應該是有人用windows開發的,送出時未做crlf轉換。我印象中git是會自動轉換crlf的,為何還會出現這種問題呢?下面是搜到的一個解釋:

原文位址:在Git中一定要關注的crlf自動轉換

GitHub 第一坑:換行符自動轉換

如果你已經做出了錯誤的選擇,也不需要重新安裝,可以直接使用指令行來修改設定。很簡單,直接打開這貨自帶的指令行工具 Git Bash,輸入以下指令,再敲回車即可:

git config --global core.autocrlf false

在各作業系統下,文本檔案所使用的換行符是不一樣的。UNIX/Linux 使用的是 0x0A(LF),早期的 Mac OS 使用的是 0x0D(CR),後來的 OS X 在更換核心後與 UNIX 保持一緻了。但 DOS/Windows 一直使用 0x0D0A(CRLF)作為換行符。(不知道 Bill Gates 是怎麼想的,雙向相容?)

這種不統一确實對跨平台的檔案交換帶來麻煩。雖然靠譜的文本編輯器和 IDE 都支援這幾種換行符,但檔案在儲存時總要有一個固定的标準啊,比如跨平台協作的項目源碼,到底儲存為哪種風格的換行符呢?

Git 作為一個源碼版本控制系統,以一種(我看起來)有點越俎代庖、自作聰明的态度,對這個問題提供了一個“解決方案”。

Git 由大名鼎鼎的 Linus 開發,最初隻可運作于 *nix 系統,是以推薦隻将 UNIX 風格的換行符儲存入庫。但它也考慮到了跨平台協作的場景,并且提供了一個“換行符自動轉換”功能。

安裝好 GitHub 的 Windows 用戶端之後,這個功能預設處于“自動模式”。當你在簽出檔案時,Git 試圖将 UNIX 換行符(LF)替換為 Windows 的換行符(CRLF);當你在送出檔案時,它又試圖将 CRLF 替換為 LF。

這是一個相當大的坑,Windows 下的中文開發者幾乎都會中招。舉個例子,你在 Windows 下用預設狀态的 Git 簽出一個檔案,寫了一行中文注釋(或者這個檔案本來就包含中文),然後存盤送出……不經意間,你的檔案就被毀掉了。

因為你送出到倉庫的檔案已經完全變成了 Windows 風格(簽出時把 UNIX 風格轉成了 Windows 風格但送出時并沒有轉換),每一行都有修改(參見本文開頭的示意圖),而這個修改又不可見(大多數 diff 工具很難清楚地顯示出換行符),這最終導緻誰也看不出你這次送出到底修改了什麼。

這還沒完。如果其他小夥伴發現了這個問題、又好心地把換行符改了回來,然後你又再次重演上面的悲劇,那麼這個檔案的編輯曆史基本上就成為一個謎團了。

由于老外幾乎不可能踩到這個坑,使得這個 bug 一直隐秘地存在着。但在網上随便搜一下,就會發現受害者絕對不止我一個。

如何解決:

  1. 使用dos2unix轉換換行符為LF,反向轉換請用unix2dos;
  2. windows使用者做開發注意送出時換行符的變化,正确設定

    core.autocrlf

    ,特别是使用WSL的時候;
  3. 大招:使用

    .gitattributes

    指明檔案類型和換行符格式等。詳見git-scm文檔,模闆在這裡。
參考: https://www.jianshu.com/p/fa4d5963b6c8