前幾天介紹了將 git diff 差異報告轉成 HTML 的簡便做法,讀者 LinnieKao 留言問到 git diff 顯示選項的問題,這裡補充說明。

diff2html 產生的左右對照比較表是最不花腦力最容易理解的形式,任何人都能輕易指出差異所在(看不看得懂程式在寫什麼是另一回事),但缺點是資料量變大數十倍。若審閱者能接受純文字的精簡形式,git diff 還提供一些較易閱讀的顯示選項

直接用實例示範,假設有個文字檔內含一行英文一行中文,修改前長這樣:

This is the content before modification.  
這是修改前的中文內容。

然後我們將 before 改成 after,修改「前」改成修改「後」,git diff 預設的差異報告會將不同處整行顯示出來:

-This is the content before modification.  
-這是修改前的中文內容。
\ No newline at end of file
+This is the content after modification.  
+這是修改後的中文內容。
\ No newline at end of file

這種資料結構非常適合程式處理,但人工閱讀時必須在上下找到同一行內容並用肉眼找出差異,較耗費腦力。因此,git diff 也提供穿插顯示的選項,加上 --word-diff 參數後差異對照會直接嵌在內容裡:

This is the content {-before-}{+after+} modification.
{-這是修改前的中文內容。-}{+這是修改後的中文內容。+}

wrod-diff 以空白區分字詞單位(Word),不含空白的整串中文會被視一個字詞,突顯效果遠不如英文,實務應用時程式碼仍以英文為主,其實效果還不錯。

如果不想看到 {- -} {+ +},使用 --word-diff=color 參數(或寫成 --color-words)就會只用顏色顯示舊版與新版內容。(注意:不適用於轉存成文字檔的應用場合)

This is the content beforeafter modification.
這是修改前的中文內容。這是修改後的中文內容。

有鑑於用空白切割字詞不夠精準,--word-diff-regex=. 允許你用 Regular Expression 定義比對依據,輸入萬用字元 . 的話意味以單一字元為標示單位,故結果如下:(不想看到 {+ +} {- -} 可再加上 --word-diff=color)

This is the content {-be-}{+a+}f{-or-}{+t+}e{+r+} modification.
這是修改{+前+}{-後-}的中文內容。

以下則是實際執行結果:

眼尖的同學可能會發現上圖是在 Linux 執行的結果,原因是 word-diff-regex=. 在 Windows 平台執行有點問題,有異動的中文字元被拆成三個 ASCII 字元(UTF-8 編碼)分別顯示,冒出 <E5>、<89>... 等符號。

一般來說,將環境變數 LANG 設成 C.UTF-8 可以克服這個問題,但是 Git for Windows 不支援 LANG 變數。參考 stackoverflow 上的討論,我找到在 Windows 正確顯示的克難解法 - 用 Cmder 跑 bash 或 mintty 跑 git diff,設定 LANG=C.UTF-8,且使用 word-diff-regex=$'[^\x80-\xBF][\x80-\xBF]*' 識別 UTF-8 字元:

export LANG=C.UTF-8
git diff --no-index --word-diff-regex=$'[^\x80-\xBF][\x80-\xBF]*' test1.txt test2.txt

實測成功:

同場加映,git diff 預設的舊版顏色標示為暗紅,在黑底視窗不太明顯,可以透過 git config color.diff.old the_color 自訂 (加 --global 可套用到所有 Git Repository),例如改成黃色:

顏色部分支援 normal, black, red, green, yellow, blue, magenta, cyan, white 等名稱,可以加上 bright 改為亮色(例如 brightred),若終端機支援,也可直接設定 RGB 色碼(如 #ff0ab3),另外還有 bold, blink, ul, italic... 等等效果,詳細說明可參考官方文件

Tips of how to use git diff options to provide more readable difference report and how to solve the charset issue for Git for Windows.


Comments

# by lonniekao

受教了,謝謝您的分享。

# by MT

用 linux 的話, 可以設定 alias 來用 vimdiff 做 git diff 在 ~/.gitconfig 裡頭這樣設定: [alias] d = difftool [diff] tool = vimdiff [difftool] prompt = false 然後只要 git d hash1..hash2 filename 就會看到左右並排的 vimdiff 了 不過喜不喜歡用 vim 那又是另外一回事...

# by Jeffrey

to MT,對某些人,說服他用 vim,他寧可選擇學習直接看 diff 文字檔,哈!

Post a comment