1. 程式人生 > >git Rebase 代替合併

git Rebase 代替合併

雖然合併(merge)操作可以用來簡單和方便地整合改動,但是它卻不是唯一的方法。“Rebase” 就是另一種替代手段。

註釋

雖然 rebase 相對於我們已知的整合操作來說有著比較顯著的優點,但是這也是在很大程度上取決於個人的喜好。一些團隊喜歡使用 rebase,而另一些可能傾向於使用合併。

Rebase 相對於合併來說是比較複雜的。我建議你可以跳過這一章,除非你和你的團隊確定會用到 rebase 操作。當你積累了 Git 的一些基本使用流程的實踐經驗後,你也可以在以後的時間再回來學習本章的內容。

深入瞭解合併操作

在你進入 rebase 這個主題前,我們有必要來再次探討一下更多關於合併操作的細節。當 Git 執行一個合併時,它實際上會查詢三個提交:

  • (1)共同的原始提交
    如果你在專案中檢視兩個分支的歷史,它們總是會出自於一次共同的提交,那麼在當時的時間點上,這兩個分支還是擁有相同的內容。之後它們就開始有了差別。
  • (2) + (3) 兩個分支的最終點
    合併操作的目的就是把兩個分支的最新狀態結合起來。因此他們各自的最新版本是有特殊含義的。

結合這三個提交後得到的結果就是我們整合的目標。

快進或合併提交

一種最簡單的情況是,在其中的一個分支上沒有任何一個新的改動提交發生。那麼在它之前的最後一次提交就仍然還是那個共同的原始提交。

在這種情況下,執行整合操作就非常簡單了。 Git 僅僅需要新增所有那些在另外一個分支上的新提交就可以了。在 Git 中,這種最簡單的整合操作我們稱之為 “快進(fast-forward)”合併。之後兩個分支就擁有了完全相同的歷史。

但是在大多數情況下,兩個分支都會有自己不同的發展軌跡。

為了完成整合,Git 會需要建立一個新的提交來含括它們之間的差異,這就是整合提交(merge commit)。

手工提交與合併提交

通常情況下,提交都是由手工精心建立的。這樣也就能更好地保證一次提交只涉及一個關聯改動,並且能更好地註釋這個提交。

一個合併提交就不同了,它不是由開發人員手動建立的,而是由 Git 自動生成的。它也不涉及一個關聯改動,其目的只是連線兩個分支,就像節點一樣。如果之後想要了解某個合併操作,你只需要檢視這兩個分支的歷史記錄和它們相應的提交樹(version tree)。

Rebase 整合

有些人並不喜歡使用這種自動合併提交。相反,他們希望專案擁有一個單一的歷史發展軌跡。比如一條直線。在歷史紀錄上沒有跡象表明在某些時間它被分成過多個分支。

現在就讓我們一步一步地瞭解一下 rebase 操作吧!仍然來使用前面的例子:我們想合併分支 B 到 分支 A 中,但是這次使用 rebase 操作。

使用下面這個非常的簡單的命令:

$ git rebase branch-B

首先,Git 會 “撤銷” 所有在分支 A 上的那些在與分支 B 的共同提交之後發生的提交。當然,Git 不會真的放棄這些提交,其實你可以把這些撤銷的提交想像成 “被暫時地儲存” 到另外的一個地方去了。

接下來它會整合那些在分支 B(這個我們想要整合的分支)上的還未整合的提交到分支 A 中。在這個時間點,這兩個分支看起來會是一模一樣的。

最後,那些在分支 A 的新的提交(也就是第一步中自動撤銷掉的那些提交)會被重新應用到這個分支上,但是在不同的位置上,在那些從分支 B 被整合過來的提交之後,它們就被 re-based 了。
整個專案開發軌跡看起來就像發生在一條直線上。相對於一個合併提交,rebase 包括了所有的組合變化,最原始的提交結構會被保留下來。

Rebase 存在的陷阱

當然,使用 rebase 操作不會是永遠一帆風順的。很有可能會搬起石頭砸自己的腳,因此你不能忽視一個重要的事實:rebase 會改寫歷史記錄

你有可能已經注意到了,在被 rebase 操作之後的版本中,提交 “C3*” 存在一個新新增的星號。這是因為,儘管這個提交的內容和 “C3” 完全一樣,但是它實際上是一個不同的提交。這樣做的原因是,它現在有一個新的源提交 C4(在最初建立 C3 時的源提交是 C1)。

一個提交僅僅包括很少的屬性,比如作者,日期,變動和誰是它的父提交。如果改變其中任何一個資訊,就必須建立一個全新的提交。當然,新的提交也會擁有一個新的 hash ID 。

如果還僅僅只是操作那些尚未釋出的提交,重寫歷史記錄本身也沒有什麼很大的問題。但是如果你重寫了已經發布到公共伺服器上的提交歷史,這樣做就非常危險了。其他的開發人員可能這時已經在最原始的提交 C3 上開始工作,並使它成為了一些新提交中不可或缺的部分,而現在你卻把 C3 的改動設定到了另一個時間點(就是那個新的 C3*)。除此之外,通過rebase 操作,這個原始的 C3 還被刪除掉了,這將是非常可怕的……

因此你應該只使用 rebase 來清理你的本地工作,千萬不要嘗試著對那些已經被髮布的提交進行這個操作。

from: https://www.git-tower.com/learn/git/ebook/cn/command-line/advanced-topics/rebase