前面介紹了 git merge
指令合併分支,本篇就來介紹另一種方式: Rebase 。
從 Rebase 字面來看,是 re 加上 base ,可以理解成「重新定義分支的參考基準」。
使用 git rebase
指令等於是修改歷史,他會使分支移動到不同的 Commit 重新定義基準點。
而 git rebase
指令與 git merge
指令最大的差異是什麼呢?
👉 git rebase
指令不會額外產生新的 Commit 來合併兩個分支。
先從以下範例來看整個關係圖:
假設現在有兩個從 master 分支上的 Commit 出去的兩個分支,分別是 one 分支與 two 分支。並且都比 master 領先兩個版本。
👉 情況:使用 git rebase 指令來執行 one 分支合併 two 分支
// 確認當前位於 one 分支上
$ git rebase two # 合併 two 分支
使用 git log 指令查看現在分支與 Commit 的關係:
可以發現到本來 two 分支上的 Commit 的 SHA-1 值改變了。
379365
→7f562c
0807ce
→9e0cd0
這過程中是做了哪些事呢?我們可以一一拆解
A1 這個 Commit 要接到 two 分支上的 B1 Commit 上,因為 A1 先前的 Commit 基準點改變了,因此需要重新計算 A1 的 SHA-1 值,就會產生新的 Commit 物件 B1 。
而原本接著 A1 的 A2 Commit ,要接到 two 分支上時,原先的 A1 已變成 B1 ,Commit 的 SHA-1 值被改變了,因此 A2 這個 Commit 也需要重新計算新的 SHA-1 值,而產生新的 Commit 物件。
最後,原本 one 分支指向的 A2 這個 Commit 會改成 B2 這個 Commit 上。
上述計算的過程,在我們執行 git rebase 指令後得到的回饋也有顯示:Applying
意思就是說 git 在重新計算這個 Commit 的 SHA-1 值。
補充|那原本的 Commit 會不見嗎?答案是不會的,這些 Commit 依然存在,只是沒有一個分支指向他們。一段時間後,就會透過 Git 的資源回收機制回收走了。
同樣地,我們可以思考 git rebase 指令中誰合併誰會有差異嗎?
如果以最終結果來看,誰合併誰並沒有差異,但過程中的歷史紀錄會有差別喔!
方法|
因為使用 git rebase
指令會導致 Commit 的 SHA-1 值改變,就不能透過 git reset HEAD^--hard
的方式回到合併前的狀態。
如果使用
git reset HEAD^--hard
指令,只會拆解最後一個 Commit 而已。
Reflog |使用 Reflog 查看紀錄找回我們執行 rebase 指令時的 SHA-1 值。
$ git reflog # 查詢變更軌跡
找到相對應的 SHA-1 值後,可以執行以下指令回到當時的狀態。
$ git reset [指定的 SHA-1 值] --hard # 還原指定的 Commit 狀態
如此一來就可以回到執行 git rebase
指令前的狀態囉!
ORIG_HEAD
ORIG_HEAD 會紀錄「危險操作」之前的 HEAD 位置。
$ git reset ORIG_HEAD --hard
👉 補充|什麼是 ORIG_HEAD
.git 目錄裡除了有 HEAD 檔案,也有一個叫做 ORIG_HEAD 的檔案。在這檔案裡會紀錄「危險操作」之前的 HEAD 位置。
什麼是危險操作?舉凡執行 merge
、rebase
、reset
這些指令有可能造成歷史紀錄的變動的動作,那麼在執行之前 HEAD 的狀態有可能被記錄在 ORIG_HEAD 的檔案裡。
使用 rebase 的優勢
缺點:相較一般的合併來得沒那麼直覺。
上述有提到 rebase 等於是修改歷史,因此要避免修改已經推出去的歷史,否則會帶給合作者的困擾。
👉 對於已經推出去的內容,非必要情況時避免使用 Rebase 。
參考文章:https://www.maxlist.xyz/2020/05/02/git-merge-rebase/