前言
目前我們已經學會如何提交、切換、還原與重製版本了,現在只差比對了;身為版控的主流,Git 本身就已擁有強大的版本比對功能,在我們之前的分支合併衝突文章中,Git 之所以能夠告訴我們在何處發生了衝突,就是因為在內部運用了版本比對功能,事實上,我們也可以自己進行版本比對,這樣在合併分支時就不會造成所謂的衝突,除此之外,當你今天想要了解特定版本之間的差異性,也可以透過版本比對功能一目了然,省去了大部分時間。
筆記重點
- 比對 HEAD 與 uncommitted 差異
- 比對 HEAD 與指定版本差異
- 比對不同版本間差異
- 使用 difftool 比對檔案
- Git 指令回顧
比對 HEAD 與 uncommitted 差異
讓我們先新增一個資料夾並提交數個 commit 紀錄:
1 | mkdir project |
這邊做一個指令的補充:
1 | git commit -am 'message' |
完整指令為:
1 | git commit -a -m 'message' |
-m
大家應該都很熟悉了才對,即提交訊息,-a
全名為 --all
,可使狀態為 Changes not staged for commit 或 Changes to be committed 的檔案直接被提交至數據庫,省略了 git add
動作,但要注意 Untracked files 狀態的檔案是不受此命令作用的。
讓我們來看目前的日誌長什麼樣子:
現在請隨意修改 index.html
與 all.css
成以下狀態:
在這邊我們只有將 all.css
的修改提交至索引區,而 index.html
的修改則是還停留在工作目錄,接著請執行以下命令:
1 | git diff |
這是比對檔案中最基本的指令,主要比對 HEAD (這指最新的 commit 紀錄) 與尚未進索引區 (unstaged) 全部檔案的差異,結果如下:
這邊你會發現只有 index.html
被進行比對,因為 all.css
已經被提交至索引區了,不在比對的範圍,如果你想比對以進索引區 (staged) 全部檔案的差異,也就是 all.css
的差異,可以使用以下指令:
1 | git diff --cached |
這樣便可比對目前 HEAD (這指最新 commit 紀錄) 與以進索引區 (staged) 全部檔案的差異,此時結果如下:
--cached
代表只比對 uncommitted 狀態下的已進索引區 (staged) 檔案,與 --staged
結果相同,後者只是前者的別名,兩者作用完全一樣。
那假設我們要同時比對尚未進索引區 (unstaged) 與已進索引區 (staged) 的檔案呢?可以使用以下指令:
1 | git diff HEAD |
這道指令代表自從上次 commit 以來做了什麼變化,這邊的 HEAD
也可以換成最新 commit 紀錄的 SHA-1 值,此時結果如下:
以上就是 uncommitted 狀態如何進行比對的各種方式,讓我們簡單說明一下比對的標示:
diff --git
:將哪兩個檔案進行比對10064
:檔案屬性,表示 Regular non-executable file100664
:Regular non-executable group-writeable file100755
:Regular executable file120000
:Symbolic link160000
:Gitlink
@@ -1,3 +1,7 @@
:前面為舊版本總行數,後面為新版本總行數
比對 HEAD 與指定版本差異
上面都是介紹 uncommitted 狀態與 HEAD (這指最新 commit 紀錄) 比對的差異,以確認在每次提交 commit 時做了些什麼事情,事實上,我們也可以指定比對的版本,輸入以下指令:
1 | git diff HEAD~1 |
之前我們有提到 ^
與 ~
相對路徑的表示方法,這邊我們使用 ~1
比較 HEAD
的前一個版本差異,此時結果如下:
在添加指定版本的 git diff 指令中,預設比對的是 HEAD (這指最新 commit 紀錄),但你會發現它連同 uncommitted 的內容也進行了比對,我個人建議,如果你要指定版本進行比對,最好在無 uncommitted 狀態下進行比對,避免混亂,執行以下命令:
1 | git add . |
因為我們又一次提交了 commit 紀錄,所以相對路徑須改為 ~2
:
1 | git diff HEAD~2 |
此時結果為:
這樣就可以確保當前比對的版本為 HEAD (指最新 commit 紀錄) 與 HEAD 的前一個版本。
比對不同版本間差異
事實上,剛剛的 git diff HEAD~2
等同於以下指令:
1 | git diff HEAD^^ HEAD |
我們可以比對指定兩個版本間的差異,前面的 HEAD^^
代表較舊的版本,後面的 HEAD
代表較新的版本,千萬不要把兩者寫反了,這樣的結果也會是相反的,讓我們試試比較不同的版本:
請注意,我們之前有提到 HEAD
代表的是我們當前所在的版本,你也可以使用 SHA-1 值作為比對的依據,任何能代表 commit 節點的稱謂都可以。
使用 difftool 比對檔案
到這邊你會發現 diff
都是在 Terminal 內顯示以進行比對,在較單純的情況下,是沒什麼問題,但只要檔案結構一變複雜,查看起來真的挺費勁的。
Git 自己也深知這點,所以提供對第三方 diff 工具的支持;在之前的 Vim 章節,我們就有嘗試將預設的 Vim 編輯器更改為 VSCode,在這邊我們也如法炮製,將 VScode 設置為我們的比對工具,以下為示範:
通過 git bash 配置 difftool (VSCode 示範):
1 | git config --global diff.tool vscode |
通過 .gitconfig
配置 difftool (VSCode 示範):
1 | [diff] |
此時即可使用 difftool
比對檔案:
1 | git difftool -y HEAD^ |
這邊的 -y
代表同意啟動第三方比對工具,如果沒有設置,在每次開啟比對檔案時,都會詢問是否同意開啟,你也可以使用以下命令全局關閉對話提示:
1 | git config --global difftool.prompt false |
讓我們來看結果如何:
Git 指令回顧
1 | # 省略 git add 提交至本地數據庫 (限以追蹤或存在於索引區檔案) |