# 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 來清理你的本地工作,千萬不要嘗試著對那些已經被發布的提交進行這個操作。
- Learn Version Control with Git 中文版
- 前言
- Part 1 - 基礎知識
- 什么是版本控制?
- 為什么要使用版本控制系統?
- 準備工作
- 版本控制的基本工作流程
- 從一個未被納入版本控制的項目開始
- 從一個已被納入版本控制的項目開始
- 工作在你的項目上
- Part 2 - 分支與合并
- 分支可以改變你的生命
- 在分支上工作
- 暫時保存更改
- 切換一個本地分支
- 合并改動
- 分支的工作流程
- Part 3 - 遠程倉庫
- 關于遠程倉庫
- 連接一個遠程倉庫
- 查看遠程數據
- 整合遠程的改動
- 發布一個本地分支
- 刪除分支
- Part 4 - 高級應用
- 撤銷操作
- 用 diff 來檢查改動
- 處理合并沖突
- Rebase 代替合并
- 子模塊
- git-flow 的工作流程
- 使用 SSH 公鑰驗證
- Part 5 - 工具與服務
- 桌面應用程序
- 比較和整合工具
- 代碼托管服務
- 更多學習資源
- 附錄
- 版本控制的最佳實踐
- 命令 101
- 從 Subversion 過渡到 Git
- 為什么選擇 Git