前段時(shí)間由于某種原因藻茂,開始接手開發(fā)公司前端Vue搭建的項(xiàng)目
該前端項(xiàng)目采用的是基于git rebase的形式去合并代碼驹暑,而我之前使用git一直都是采用merge的形式合并分支代碼,對于rebase一概不知
故此利用碎片時(shí)間學(xué)習(xí)整理一下關(guān)于git rebase的原理以及其和git merge的區(qū)別是什么辨赐,我會(huì)采用實(shí)際的案例描述二者的區(qū)別
準(zhǔn)備工作
git 客戶端安裝(只要git bash即可)
github上新建一個(gè)項(xiàng)目
- 項(xiàng)目clone到本地
clone完成以后進(jìn)入該項(xiàng)目文件夾下优俘,準(zhǔn)備工作完畢
模擬日常開發(fā)
同學(xué)A:
- 執(zhí)行g(shù)it log
可以看出此時(shí)該項(xiàng)目僅有一次提交記錄
- 執(zhí)行新增文件a.txt,并本地提交一次后再次執(zhí)行g(shù)it log
這個(gè)時(shí)候打開github掀序,刷新該項(xiàng)目的commit記錄
發(fā)現(xiàn)遠(yuǎn)程倉庫還是只有一次提交記錄的帆焕,說明A同學(xué)還沒有將自己最新的修改push到遠(yuǎn)程倉庫,其他同學(xué)這個(gè)時(shí)候是看不到A的最新提交的
- A同學(xué)將自己的最新提交Push到遠(yuǎn)程倉庫
- 再次刷新github 提交記錄不恭,發(fā)現(xiàn)已經(jīng)多了一個(gè)A同學(xué)提交的最新記錄了
切分支開發(fā)
- 基于已有兩次提交記錄的本地master分支檢出一個(gè)新分支dev叶雹,并將該分支推到遠(yuǎn)程倉庫
- 查看遠(yuǎn)程倉庫,多了一個(gè)dev分支
- 此時(shí)本地的git分支圖類似如下
A同學(xué)開發(fā)功能
假設(shè)A同學(xué)基于dev分支開發(fā)功能换吧,在本地新做了三次代碼提交输钩,git log
如下
那么此時(shí)的git分支圖如下
- 重點(diǎn)
如果此時(shí)在A同學(xué)準(zhǔn)備進(jìn)行第四次本地提交之前瞧挤,另一個(gè)同學(xué)B向遠(yuǎn)程倉庫推送了一個(gè)master分支的提交,即此時(shí)master實(shí)際的提交已經(jīng)向前走了
我們這個(gè)時(shí)候在github上操作一次commit,模擬另一個(gè)同學(xué)此時(shí)push了master分支
- A同學(xué)本地更新一下master分支
發(fā)現(xiàn)master分支已經(jīng)向前走了一次提交雀摘,此時(shí)的分支圖如下
此時(shí)我們知道A同學(xué)開發(fā)的dev分支是基于C2提交點(diǎn)切出來的生蚁,而這個(gè)時(shí)候master分支已經(jīng)被更新了
如果A同學(xué)開發(fā)完畢,需要將其所作的功能合并到master分支 ,他可以有兩種選擇
直接git merge
如果A同學(xué)選擇用git merge的方式進(jìn)行合并dev到master分支编饺,那么git會(huì)這么做
找出dev分支和master分支的最近共同祖先commit點(diǎn),即C2
將dev最新一次commit(C5)和master最新一次commit(C6)合并后生成一個(gè)新的commit(C7)响驴,有沖突的話需要解決沖突
將以上兩個(gè)分支dev和master上的所有提交點(diǎn)(從C2以后的)按照提交時(shí)間的先后順序進(jìn)行依次放到master分支上
git rebase 后再git merge
rebase之前需要經(jīng)master分支拉到最新
切換分支到需要rebase的分支透且,這里是dev分支
執(zhí)行g(shù)it rebase master,有沖突就解決沖突豁鲤,解決后直接git add . 再git rebase --continue即可
此時(shí)的git log如下
可以發(fā)現(xiàn)其一并沒有多出一次commit秽誊,其二dev后面幾次提交的commit hash值已經(jīng)變了,包括C3琳骡,C4锅论,C5
- 切換到master分支,執(zhí)行g(shù)it merge dev
發(fā)現(xiàn)采用rebase的方式進(jìn)行分支合并楣号,整個(gè)master分支并沒有多出一個(gè)新的commit最易,原來dev分支上的那幾次(C3,C4炫狱,C5)commit在rebase之后其hash值發(fā)生了變化藻懒,不在是當(dāng)初在dev分支上提交的時(shí)候的hash值了,但是提交的內(nèi)容被全部復(fù)制保留了视译,并且整個(gè)master分支的commit記錄呈線性記錄
其分支圖最終如下
總結(jié)
git merge 操作合并分支會(huì)讓兩個(gè)分支的每一次提交都按照提交時(shí)間(并不是push時(shí)間)排序嬉荆,并且會(huì)將兩個(gè)分支的最新一次commit點(diǎn)進(jìn)行合并成一個(gè)新的commit,最終的分支樹呈現(xiàn)非整條線性直線的形式
git rebase操作實(shí)際上是將當(dāng)前執(zhí)行rebase分支的所有基于原分支提交點(diǎn)之后的commit打散成一個(gè)一個(gè)的patch酷含,并重新生成一個(gè)新的commit hash值员寇,再次基于原分支目前最新的commit點(diǎn)上進(jìn)行提交,并不根據(jù)兩個(gè)分支上實(shí)際的每次提交的時(shí)間點(diǎn)排序第美,rebase完成后蝶锋,切到基分支進(jìn)行合并另一個(gè)分支時(shí)也不會(huì)生成一個(gè)新的commit點(diǎn),可以保持整個(gè)分支樹的完美線性
另外值得一提的是什往,當(dāng)我們開發(fā)一個(gè)功能時(shí)扳缕,可能會(huì)在本地有無數(shù)次commit,而你實(shí)際上在你的master分支上只想顯示每一個(gè)功能測試完成后的一次完整提交記錄就好了别威,其他的提交記錄并不想將來全部保留在你的master分支上躯舔,那么rebase將會(huì)是一個(gè)好的選擇,他可以在rebase時(shí)將本地多次的commit合并成一個(gè)commit省古,還可以修改commit的描述等
最后
如果你想要你的分支樹呈現(xiàn)簡潔粥庄,不羅嗦,線性的commit記錄豺妓,那就采用rebase
否則惜互,就用merge吧