概念
變基(Rebase)也是合代碼的一種手段。
變基與合并(Merge)不同的是,他可以修改歷史,使用rebase來代替merge合代碼的話,得到的歷史記錄是一條直線提交歷史,無分叉,很漂亮。
然而這也是它的缺點,它抹去了分支歷史信息,無法追溯。
指令
變基指令和合并類似,也是對分支進行操作,所以需要指定一個分支名
git rebase 分支名
合并時所指定的分支,是被合進來的分支,意思是把別人的東西納入給自己。
而變基的數(shù)據(jù)流向似是相反,變基指令所指定的分支,是自己將要注入的目的地。
變基指令發(fā)出時,是把自己接在目標分支的后面,所以變基變的是自己。
merge和rebase的數(shù)據(jù)流向
你可能會疑惑,當我要把兩個分支合并時,或者變基時,是要站在分支1的角度合分支2,還是反過來?
為此,來做個實驗,搞清楚它們的方向。這里我起了個名字叫數(shù)據(jù)流向,可能起得不恰當,將就著看,意思懂就行,不用執(zhí)著文字相。
公共祖先
創(chuàng)建一個空倉庫,默認得到一個master分支,任意放個文件,進行一次初始化提交。
git init
touch foo.txt
git add --all
git commit -m "init"
然后再創(chuàng)建一個分支feature
git branch feature

這時,分支master和分支feature都指向初始提交,這個提交點作為兩條分支的公共祖先。
并行開發(fā)
現(xiàn)在讓master分支和feature分支有其各自的修改提交,且提交時間無序,我們來模擬這個情景。
### 在master分支提交MA
git checkout master
touch MA.txt
git add --all
git commit -m "MA"
### 在feature分支提交FA
git checkout feature
touch FA.txt
git add --all
git commit -m "FA"
### 在master分支提交MB
git checkout master
touch MB.txt
git add --all
git commit -m "MB"
### 在feature分支提交FB
git checkout feature
touch FB.txt
git add --all
git commit -m "FB"

現(xiàn)在前置工作準備好了,可以把項目復制4份,以便進行幾種合并結果的比較。
四種合代碼方式
接下來,我們嘗試四種合代碼方式,分別是:
- merge master
- merge feature
- rebase master
- rebase feature
對復制的4份項目,分別執(zhí)行指令,得到如下結果:

git merge master:在feature分支上發(fā)出合并指令,這樣會把master分支的提交合到feature自己身上,然后再創(chuàng)建一次合并提交。

git merge feature:在master分支上發(fā)出合并指令,這樣會把feature分支的提交合到master自己身上,然后再創(chuàng)建一次合并提交。

git rebase feature:在master分支上發(fā)出變基指令,這樣會把master分支異于feature分支的提交接在feature之后。

git rebase master:在feature分支上發(fā)出變基指令,這樣會把feature分支異于master分支的提交接在master之后。
比較幾種合代碼的情況,如果要進行merge操作的話,最好是在主分支上執(zhí)行merge,把次分支的代碼合進來;如果要進行rebase操作的話,最好是在次分支上進行,把自己變基合入主分支。
變基的工作原理
變基其實是復制要被變基的分支上的提交,然后在別的分支上把提交依次重演出來。
注意這是復制,而不是移動。也就是說,舊有分支的提交還是可以通過hash值找回來的,在沒被gc清理的前提下。
由于變基的原理是復制,這導致產(chǎn)生新的提交。在上一小節(jié)的實驗中,比如rebase master操作,從現(xiàn)實時間上來說,MB提交是遲于FA提交中,但變基結果是FA在MB之后,為什么?
因為變基后的FA已經(jīng)不是原feature分支上的FA了,它是在變基過程中新產(chǎn)生的一個復制結果,其提交信息也已經(jīng)被改變。
再者,變基完成后,從版本庫歷史上,也已經(jīng)看不出哪些提交是屬于哪個分支的了。
可以說,變基修改了歷史。
變基的沖突
在合并時會遇到的沖突情況,在變基時也一樣不能避免。
由于變基過程,是一個一個新復制的提交在另一條分支上重演出來,所以可能會出現(xiàn)多次沖突的情況。
在提交重演的時候,每遇到一次沖突,變基過程就會暫停下來,這時,你需要手動處理沖突的文件,處理完后add到暫存區(qū),然后使用如下指令讓變基繼續(xù)。
git rebase --continue
當然,如果你有很多個提交在重演時都沖突的話,意味著你需要多做幾次continue...
移植分支
普通變基的指令是這樣的: git rebase master
移植分支的指令是這樣的:git rebase master --onto 另一分支名
怎么理解?
如果不加--onto選項,其實是把自己移植到了目標分支master上,如果加了--onto 分支名,就會把原本要接到目標master的提交,拐了個彎,接到了指定的另一個分支那里去。
就這么回事^ ^。