文章目錄
這篇文章是兩篇教學其中一篇『how git works 』的下半段,可以很清楚弄清楚 merge 跟 rebase 的差別。
rebase 要解決什麼問題
隨著 commit 增加,merge 會讓 git log 看起來非常混亂
rebase 去除不必要的多餘細節,讓圖形能讓人短時間內看懂。
rebase 的原理
簡單說,植物嫁接的概念:但是不是『剪下貼上』,而是『複製貼上』
rebase 會創建 commit 的副本
rebase 創建了相同數據的新 commit ,所以這些新的 commit 看起來幾乎完全像原始 commit ,但是它們是具有新SHA1的新對象。
最後,分支移動到新的 commit ,將舊 commit 留下。
舊 commit 會發生什麼情況?在這種情況下,這些 commit 並不是非常有用。 沒有分支指向他們。如果你有記錄下了它們的 SHA1,那麼你仍然可以 check out 到那邊。
跟 HEAD detached 一樣,如果一直沒人來找它,過一段時間就會被 Git 資源回收機制給收掉。
rebase 是破壞性的
rebase 的這種整潔效果是有代價的。commit 的歷史並不真實。
rebase 會創建新的 commit ,並且會遺留現有的 commit(過一段時間會被 Git 資源回收機制給收掉。) 。
例如,在這種情況下,它看起來像黃色 commit 首先被創建,藍色 commit 被創建在最後。事實上:黃色和藍色的 commit 是在不同分支中並行創建的。(參考文章最上方)
與 merge 相比,rebase 會改變歷史。你可能會說誰在乎最初的歷史,你只關心最後的結果。
有些狀況是需要關心歷史的:
例如,有一些高級的Git命令 ( e.g. reset ),如果您篡改歷史記錄,這些命令會變得不那麼有用。而且在 跟他人協作的時候容易發生問題。
動畫解說:
這裡的這個新的黃色 commit 與之前的黃色 commit 不同。
它是一個副本 (內容一樣,但 SHA1 不同),一個不同的數據庫對象。 用一個驚歎號標記它,原來的 commit 實際上會在某個時候被垃圾收集。
所以,再次發生衝突。
我們不能 push 到 remote ,因為 local repo 和 origin repo 有不同的歷史。
這種特殊的衝突不多,可以很容易地修復它,例如通過 false push 或 pull followed by a push。 我們都可以解決這個問題,然後在本地有相同的來源。
但是當我們引入另一個用戶時就會崩潰。
我們的朋友(安妮)仍然有原始的感嘆號,在我們的資源庫中是黃色的 commit 。
不僅如此,她還在 Lisa branch 建立新的 commit。所以現在安妮有一個非常討厭的衝突,她需要先了解發生的事情,然後才能解決衝突,即使她自己沒有引起衝突。
所以,Never rebase shared commits
即使在解決衝突之後,即使他們看起來完全一樣,最終會出現一個令人困惑的歷史 。
如果情況不那麼確定時候,請使用 merge。rebase 是一個強大的工具,但只有在您知道自己在做什麼並且了解其後果時才應該使用它。