git diff - 比較差異

git diff 用來比較檔案之間的差異,是 debug 和 code review 的好幫手。

基本用法

查看工作目錄的變更

git diff

這會顯示工作目錄暫存區之間的差異,也就是你修改了但還沒 git add 的變更。

查看暫存區的變更

git diff --staged
# 或
git diff --cached

這會顯示暫存區最後一次 commit之間的差異,也就是你 git add 了準備要 commit 的變更。

讀懂 diff 輸出

diff --git a/index.html b/index.html
index 1234567..abcdefg 100644
--- a/index.html
+++ b/index.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <title>Old Title</title>
+    <title>New Title</title>
+    <meta charset="UTF-8">
 </head>

說明:

  • --- a/index.html:修改前的檔案
  • +++ b/index.html:修改後的檔案
  • @@ -1,5 +1,6 @@:變更的位置(舊檔案第 1 行開始共 5 行,新檔案第 1 行開始共 6 行)
  • - 開頭的行:被刪除的內容
  • + 開頭的行:被新增的內容
  • 沒有符號的行:沒有變更的上下文

比較特定檔案

# 比較單一檔案
git diff index.html

# 比較多個檔案
git diff index.html style.css

# 比較特定目錄
git diff src/

比較 Commit 之間的差異

比較兩個 Commit

git diff commit1 commit2

例如:

git diff a1b2c3d b2c3d4e

比較和上一個 Commit

# 和上一個 commit 比較
git diff HEAD~1

# 和上兩個 commit 比較
git diff HEAD~2

比較特定 Commit 和現在

git diff a1b2c3d

這會比較 commit a1b2c3d 和目前工作目錄的差異。

比較分支之間的差異

# 比較兩個分支
git diff main feature

# 查看 feature 分支相對於 main 的變更
git diff main...feature

main..feature(兩個點)和 main...feature(三個點)的差異:

  • main..feature:比較兩個分支最新 commit 的差異
  • main...feature:比較從共同祖先以來 feature 分支的變更

常用選項

只顯示檔案名稱

git diff --name-only

顯示檔案名稱和狀態

git diff --name-status

輸出:

M       index.html
A       newfile.js
D       oldfile.js
  • M - Modified(修改)
  • A - Added(新增)
  • D - Deleted(刪除)

顯示統計資訊

git diff --stat

輸出:

 index.html | 5 ++---
 style.css  | 10 ++++++++++
 2 files changed, 12 insertions(+), 3 deletions(-)

忽略空白變更

# 忽略空白字元的變更
git diff -w
git diff --ignore-all-space

# 忽略行尾空白
git diff --ignore-space-at-eol

# 忽略空白數量的變更
git diff -b
git diff --ignore-space-change

顯示更多上下文

# 顯示每個變更周圍 10 行
git diff -U10

Word Diff

git diff --word-diff

以單字為單位顯示差異,而不是整行:

[-old-]{+new+} text here

顏色輸出

git diff --color-words

比較遠端分支

# 比較本地和遠端分支
git diff origin/main

# 先 fetch 再比較
git fetch origin
git diff main origin/main

實用範例

Commit 前檢查

# 查看所有未暫存的變更
git diff

# 查看即將 commit 的變更
git diff --staged

# 查看所有變更(暫存 + 未暫存)
git diff HEAD

查看某個 Commit 的變更

git diff a1b2c3d^!
# 等同於
git diff a1b2c3d~1 a1b2c3d

比較檔案的特定版本

# 查看某檔案在某個 commit 時的內容
git show a1b2c3d:index.html

# 比較某檔案在兩個 commit 之間的差異
git diff a1b2c3d b2c3d4e -- index.html

輸出到檔案

git diff > changes.patch

之後可以用 git apply changes.patch 套用這個 patch。

檢查有無差異

# 如果有差異會回傳 exit code 1
git diff --quiet

# 用在 script 中
if git diff --quiet; then
    echo "No changes"
else
    echo "Has changes"
fi

圖形化 Diff 工具

如果覺得命令列的 diff 不夠直觀,可以用圖形化工具:

git difftool

常見的 diff 工具:

  • VS Code
  • Meld
  • Beyond Compare
  • Kaleidoscope (macOS)

設定 VS Code 為 diff 工具:

git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'