在 Git 中合併來自不同分支的修改主要有兩種方法:merge
和 rebase
。
在之前的文章當中我們介紹了git merge
命令的用法,通過git merge
命令我們可以對兩個分支進行合併操作。這樣我們可以很方便地進行協同開發了,每個人都在自己的分支下開發代碼,開發完畢之後再合併到master
分支,通過這種方式可以保證大家的代碼不會陷入混亂。
但是這樣也會有隱含的缺陷:
- 一個是提交歷史記錄的不完整,回退的時候可選擇性減少。
- 一個是歷史提交記錄非常的混亂,會讓你眼花繚亂,欲仙欲死。
爲了解決這些頭疼的問題,我們就需要用到git rebase
操作。
1、git rebase命令簡介
rebase
有兩個意思:變基、衍合,即變換分支參考的基準點。默認情況下,一個分支會以該分支上的第一次提交作爲基點。
如下圖所示:master
分支默認以提交1st
作爲基點:
如果以提交
4th
作爲master
分支的基點,master
分支就會變爲:
這個變化基準點的過程就稱之爲變基(rebase
)。
接下來詳細介紹一下rebase
命令:
官方對於rebase
的描述爲:“git-rebase: Forward-port local commits to the updated upstream head”— git doc
翻譯一下,就是將你在某個分支上的所有提交記錄,移花接木到另一個分支上。
這邊需要強調一個概念:reapply
,使用rebase
並不是簡單地像你進行剪切複製一樣,rebase
命令會依次地,將你所要操作分支上的所有提交,應用到目標分支上。
也就是說,實際上在執行rebase
命令的時候,有兩個隱含的注意點:
- 在重放之前提交的時候,Git會創建新的提交。也就是說即使你重放的提交與之前的一模一樣,Git也會將他當做新的獨立的提交進行處理。
-
git rebase
命令並不會刪除舊的提交。也就是說,你在對某個分支執行了rebase
操作之後,老的提交仍然會存放在.git
文件夾的objects
目錄下。
2、merge與rebase的區別
git rebase
命令與git merge
命令的功能十分相似,不過二者的工作方式有着顯著的差異。
比如:將A
和B
兩分支進行合併:
- 在
A
分支上執行git merge B
,表示的是將B
分支合併到A
分支上; - 而在
A
分支上執行git rebase B
,則表示將A
分支通過變基合併到B
分支上;(看不懂,往下看)
(1)採用merge
合併分支
現在有兩個分支master
分支和dev
分支,如果想要將dev
分支合併到master
分支上。根據三方合併原則,需要在c4
、c6
和它們的公共父提交節點c2
的基礎上進行合併。
如下圖:
合併後生成一個新的提交c7
,該提交有兩個父節點c4
和c6
。
具體的合併方式爲:如果沒有衝突git
就會自動採用Fast-forward
方式進行合併,如果有衝突就進行典型合併,解決衝突後再進行手動合併。
如下圖:
(2)採用rebase
合併分支
我們希望dev
分支變基合併到master
分支上,所以首先切換到dev
分支(注意這裏與採用merge
方法時所在的分支相反):
如下圖:
執行命令:
# 切換分支
$ git checkout dev
# 再進行rebase合併
$ git rebase master
合併後的結果,如下圖:
注意:
被合併的master
分支保持不動,而合併它的dev
分支,將自己的提交作爲補丁(patch)一個個應用(applying)到master
指向的分支上。
在這個過程中Git會自動創建c5'
和c6'
提交。原來的c5
和c6
提交就沒用了,會被git gc
回收(就是不顯示在歷史記錄中了,但是數據還在,應該用git reflog
命令可以看到)。
合併後分支Git版本庫中的提交記錄變成了一條直線,如下圖:
(3)總結rebase命令
基於以上表述,我們可以得出git rebase
命令的工作流程:
- 在對特定分支進行
rebase
操作之後,其等效於創建了新的提交。 - 並且老的提交也沒有被銷燬,只是簡單地不能再被訪問或者使用。
- 之前分支的章節我們曾經提及,分支只是一個執行提交的指針。因此如果沒有分支或者Tag指向某個提交,該提交將無法再被訪問使用,但是該提交會一直存在於你的文件系統中,佔用着你的磁盤存儲。
git rebase master
命令的意思:
該指令翻譯過來就是:重新定位當前工作的分支,以master
分支做爲新的基準點,即使用 master
分支所指向的提交,作爲我新的基準點。
-
git merge 要合併的分支
命令:切換的主要的分支,把其他的分支合併過來。 -
git rebase 變基的目標分支
命令:切換到被合併的分支上,把該分支上的提交變基到目標分支上。
參考: