今天來談 git rebase
,這是一個對於剛開始學 GIT 的人,常常覺得有點混亂複雜的指令,他究竟在做什麼呢?今天的一開始,我們先用樂高手冊組裝來舉個例子:
有一個基板,稱為橫條基板
A 版本,基於基板,A 版本手冊有兩個步驟
B 版本,基於基板,B 版本手冊有兩個步驟
步驟 1 (B1):變更內容,在橫條基板右上角放上一格綠色樂高
步驟 2 (B2):變更內容,在一格綠色樂高下放上一格黑色樂高
如果用步驟流程看起來的畫面會像以下:
在 B 版本作者取得新的公定基板後,發現自己定義的步驟上,都不會與 A 版本的基板有不相容的地方,這時候,只需要基於新的基板,在 A 版本,重新實作一次 B 版本,就可以更新好自己的手冊。改版後的手冊會是怎麼樣呢?
新步驟 1 (B1’):變更內容,在橫條基板右上角放上一格綠色樂高
新步驟 2 (B2’):變更內容,在一格綠色樂高下放上一格黑色樂高
有沒有發現,上面的內容幾乎沒有變動,只是因為步驟基於的基底已經不一樣了,為了避免會錯意,對於步驟名稱的描述上,增加了「新」的字樣。因為新 B 版本手冊,看起來的流程畫面大概如下:
git rebase
在 GIT 上 rebase
做的事情原理也是一樣的。只是把開始的基礎換一下,在不同的基礎上重新把每個步驟再作一次。可以想像:把這個 commit 所說的步驟,試著在新的地方再做一次。
以 Day 12 git merge
提到的「兩個分支都變更了同一個檔案」案例來說:
當我們在 apple 分支上,執行 git rebase banana
會發生什麼事情?
而在 SourceTree 的介面上,也可以發現,原本 apple 分支上,兩個變更對應的兩個 commit HASH Code 91d27e5
及660033a
變更為新的 39298cb
及acc1e64
。
如果把這個步驟重新用動畫表示,可以這樣呈現:
在 Day 12 的時候,我們有強調了一次「每個 commit 都是記錄基於上一個 commit 而做的改變」,如果在 rebase 這指令上,可以說 rebase 就是「換一個基點,再做一次同樣的改變」。
因此在上面的例子中,原本 91d27e5
的這個步驟,原本基於 f8c19bf
這個步驟「新增了 apple 1 這行文字」,現在改為基於 8b7b845
這個 commit 作「新增了 apple 1 這行文字」,而因為 GIT 是使用每次的變化內容、源頭、資訊等,產生新的 HASH Code,因此這時候必須要重新產出新的 HASH Code,因而產生了對應「新增了 apple 1 這行文字」這個動作的新 HASH Code 39298cb
。同樣的 660033a
這個步驟,也必須在新的基礎 39298cb
再做一次,同樣的產出新的 HASH Code acc1e64
。
必需再強調一次「每個 commit 都是記錄基於上一個 commit 而做的改變」,rebase 則是因為現在的基礎不一樣了,所以重新產生新的 HASH Code 來對應這新的基礎變化。
既然 rebase 可以把同樣的步驟,,像樂高積木一樣,在不同的地方重新組裝、實作一次,那我可以只挑某個步驟來重新實作嗎?我們下回分曉。