同事遇到的茶包。

git diff 時某文字檔被當成二進位檔案無法顯示差異,後來發現是 Unicode 編碼(UTF-16 LE with BOM/UCS-2 LE with BOM)造成,用以下範例重現:

type a.txt 可檢視文字內容,但 git diff 比對時卻出現 "Binary a/a.txt and b/a.txt differ",未顯示修改前後差異。

爬文得知,git diff 自動偵測檔案為文字檔時會進行文字比對,但限定 UTF-8 編碼。這時要使用階技巧,在 .git/config (Repository 個別設定) 或 %userprofile%/.gitconfig (全域設定) 宣告額外 diff 轉換邏輯,例如:新增一組名為 utf16 的 diff 轉換設定,呼叫 iconv 將 utf-16 轉成 utf-8:

除了直接修改 config 或 .gitconfig,透過指令 git config diff.utf16.textconv "iconv -f utf-16 -t utf-8" 也能新增 diff 轉換。

接著,我們要用 .gitattributes 指定 git diff 那些檔案時套用編碼轉換。指定對象可以是特定路徑的檔案、特定副檔名類型、特定目錄下的檔案等,用法跟 .gitignore 一樣,套用對象後方則加上 diff=utf16,代表比對這類檔案前先進行 utf16 轉換。

a.txt diff=utf16
*.reg diff=utf16
**/somefolder diff=utf8

實測修改 .git/config 跟 .gitattributes 後,git diff 便能正確比對 UTF-16 編碼文字檔了。

舉一反三,之前遇到 BIG5 中文字變角括號的問題,應該也能用同樣技巧解決。

設定 git config diff.big5.textconv "iconv -f big5 -t utf-8",.gitattributes 加上 b.txt diff=big5,薑! 薑! 薑! 薑~~~

Tips of how to use iconv conversion to make git diff compare UTF-16 or BIG5 encoding text files.


Comments

# by 三小俠

厲害

# by Ike

.gitattributes 加上 b.txt diff=big5 意思是要個別指定檔名嗎?

# by Jeffrey

to lke,文章案例我是指定特定檔案,使用萬用字元 * 可以指定某類副檔名、特定資料夾下的所有檔案、任何資料夾下檔名包含某個關鍵字的檔案... 等等,跟在 .gitignore 的做法一樣。

# by Ike

to Jeffrey 可行,感謝~

# by typebrook

學到了,原來還有這種設定!

# by Marcel

感謝…處理MS SQL 生成的DDL時,正遇到這問題。

Post a comment