概念
變基(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)在前置工作準備好了瘫拣,可以把項目復(fù)制4份,以便進行幾種合并結(jié)果的比較告喊。
四種合代碼方式
接下來麸拄,我們嘗試四種合代碼方式,分別是:
- merge master
- merge feature
- rebase master
- rebase feature
對復(fù)制的4份項目黔姜,分別執(zhí)行指令拢切,得到如下結(jié)果:
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操作的話金赦,最好是在次分支上進行,把自己變基合入主分支对嚼。
變基的工作原理
變基其實是復(fù)制要被變基的分支上的提交夹抗,然后在別的分支上把提交依次重演出來。
注意這是復(fù)制纵竖,而不是移動漠烧。也就是說杏愤,舊有分支的提交還是可以通過hash值找回來的,在沒被gc
清理的前提下已脓。
由于變基的原理是復(fù)制珊楼,這導(dǎo)致產(chǎn)生新的提交。在上一小節(jié)的實驗中度液,比如rebase master
操作厕宗,從現(xiàn)實時間上來說,MB
提交是遲于FA
提交中堕担,但變基結(jié)果是FA
在MB
之后已慢,為什么?
因為變基后的FA
已經(jīng)不是原feature分支上的FA
了,它是在變基過程中新產(chǎn)生的一個復(fù)制結(jié)果霹购,其提交信息也已經(jīng)被改變佑惠。
再者,變基完成后齐疙,從版本庫歷史上膜楷,也已經(jīng)看不出哪些提交是屬于哪個分支的了。
可以說贞奋,變基修改了歷史赌厅。
變基的沖突
在合并時會遇到的沖突情況,在變基時也一樣不能避免轿塔。
由于變基過程特愿,是一個一個新復(fù)制的提交在另一條分支上重演出來,所以可能會出現(xiàn)多次沖突的情況催训。
在提交重演的時候,每遇到一次沖突宗收,變基過程就會暫停下來漫拭,這時,你需要手動處理沖突的文件混稽,處理完后add到暫存區(qū)采驻,然后使用如下指令讓變基繼續(xù)。
git rebase --continue
當然匈勋,如果你有很多個提交在重演時都沖突的話礼旅,意味著你需要多做幾次continue...
移植分支
普通變基的指令是這樣的: git rebase master
移植分支的指令是這樣的:git rebase master --onto 另一分支名
怎么理解?
如果不加--onto
選項洽洁,其實是把自己移植到了目標分支master上痘系,如果加了--onto 分支名
,就會把原本要接到目標master的提交饿自,拐了個彎汰翠,接到了指定的另一個分支那里去龄坪。
就這么回事^ ^。