Git Rebase 是什麼?和 Git Merge 有什麼差?

在上一篇 Git Merge 的基本觀念和使用方式 中,我們介紹了該如何透過 git merge 合併在其他分支上的所完成的工作,以及 git merge 的種類。

在這一篇中,我們要來介紹另一個合併分支的方式,那就是 git rebase!

許多人常常會認為 git rebase 只是一個整理 commit 的工具,也不知道 git rebase 和 git merge 的差異。

這章我們會從什麼是 git rebase 開始說起,接著討論實際例子,最後來比較和 git merge 的差異!

什麼是 git rebase

如果有好好讀上一章的人,一定已經很清楚分支的合併概念了。

其實 git rebase 的概念,也就是合併兩個分支。

誒那就會有人問了,既然也同樣是合併兩個分支,那和 git merge 有什麼差呢?

這個問題就是這篇文章最後要來討論的,我們先一步一步慢慢來,先知道 git rebase 也是用來合併分支的就好!

然而雖然也是合併分支,但 git rebase 合併的方式有些特別。

如上圖所示,git rebase 合併的方式是將一個分支上所有的 commit,移到另一個分支的最前面。

實際範例

光用講的和圖示對於沒有用過 git rebase 的人肯定看不懂。

這邊我們就來用一個簡單的範例,來演示一次 git rebase。

新增檔案

首先,我們在主分支 main 上建立一個 test.txt 的檔案,內容可以什麼都不用打,並建立第一筆 commit。

echo "" >> test.txt
git add test.txt
git commit -m "initial commit"
建立 feature branch

接著,我們建立一個新分支,並在 feature 分支上,建立第二個檔案 test2.txt,然後新增一個 commit。

git checkout -b feature
echo "" >> test2.txt
git add test2.txt
git commit -m "add test2.txt"
製造分歧點

接著,我們回到主分支 main 上,並修改 test.txt,接著新增一個 commit。

這會讓 main 和 feature 兩個分支產生 commit 分歧。

git checkout main
echo "test" >> test.txt
git add test.txt
git commit -m "add test to test.txt"

也就是說,現在兩個分支的 commit history 會長這樣:

執行 git rebase

接著,我們就要來藉由 git rebase 合併分支啦!

我們先要切換到 feature branch,並在上面執行 rebase。

git checkout feature
git rebase main

執行完後,我們可以利用 git log 查看 feature 分支的 commit history。

現在 feature 分支的 commit 就會變成這樣:

合併回 main

執行完 git rebase 後,feature 分支還沒有合併回 main 中。

想要合併分支,我們需要切換回主分支,然後執行 git merge。

git checkout main
git merge feature

由於 feature 分支和 main 分支現在沒有任何分歧(透過 rebase 解決掉了),因此現在的 git merge 會使用 fast-forward 的方式合併!

Merge v.s. Rebase

我們現在知道,這兩個方式都可以用來合併分支。

那麼,這兩個方式的主要差別在哪裡呢?

我們來看看下面這個表格:

功能 git merge git rebase
基本功能 通過創建一個合併 commit 來合併兩個分支。 將一系列 commit 移動或合併到新的基底上。
提交歷史 保留完整的歷史。 重寫提交歷史,並創建線性的歷史。
衝突解決 衝突在新的合併 commit 中解決。 衝突在重寫過程中解決,然後才提交。
目標分支 包含將分支結合在一起的合併提交。 包含具有新基底的重寫提交,沒有合併提交。
使用情境 當你重視完整性 當你重視易讀性
對共享歷史的影響 對於共享分支是安全的,因為它不會重寫 commit 歷史。 重寫歷史可能會在其他人共享分支時造成問題。

上面的表格大致上涵蓋了決大部分 git merge 和 git rebase 的差異。

我個人覺得最重要就是兩點:

  1. git merge 會產生一個新的 commit,而 git rebase 不會。
  2. git merge 保留完整的 commit 歷史,而 git rebase 會改寫並創建線性歷史。

由於 git rebase 會改寫歷史,因此當你有和別人一起共享同一個分支時,你會盡量不用 git rebase 去合併分支。

這是因為如果你使用 git rebase,那麼別人電腦上的 commit history 就會不同,那麼他們到時候在做 git pull 時,就會出現許多不必要的問題。

我自己個人在工作上的法則是這樣:

如果這個分支只有我自己在用,那我一律用 git rebase,因為我覺得線性的歷史比較易讀。但是當有多人同時使用當前分支,那麼就一律使用 git merge,以減少不必要的衝突!

結尾

這樣我們就介紹完 git rebase 啦!

這個功能也是每個學 git 的人都一定一定要會的技能!

要非常清楚 git merge 和 git rebase 之間的差異,也要知道在哪一種情況下應該使用哪種合併方式。

那這篇文章就到這裡啦~

以後我們還會再繼續介紹更多和 git 有關的知識和技術!

有學到東西的話歡迎給五星評價喔!