面試官:說說你對(duì)Git Rebase 和 Git Merge的理解?區(qū)別?
本文轉(zhuǎn)載自微信公眾號(hào)「JS每日一題 」,作者灰灰 。轉(zhuǎn)載本文請(qǐng)聯(lián)系JS每日一題公眾號(hào)。
一、是什么
在使用 git 進(jìn)行版本管理的項(xiàng)目中,當(dāng)完成一個(gè)特性的開發(fā)并將其合并到 master 分支時(shí),會(huì)有兩種方式:
- git merge
- git rebase
git rebase 與 git merge都有相同的作用,都是將一個(gè)分支的提交合并到另一分支上,但是在原理上卻不相同
用法上兩者也十分的簡(jiǎn)單:
git merge
將當(dāng)前分支合并到指定分支,命令用法如下:
- git merge xxx
git rebase
將當(dāng)前分支移植到指定分支或指定commit之上,用法如下:
- git rebase -i <commit>
常見的參數(shù)有--continue,用于解決沖突之后,繼續(xù)執(zhí)行rebase
- git rebase --continue
二、分析
git merge
通過git merge將當(dāng)前分支與xxx分支合并,產(chǎn)生的新的commit對(duì)象有兩個(gè)父節(jié)點(diǎn)
如果“指定分支”本身是當(dāng)前分支的一個(gè)直接子節(jié)點(diǎn),則會(huì)產(chǎn)生快照合并
舉個(gè)例子,bugfix分支是從master分支分叉出來的,如下所示:
合并bugfix分支到master分支時(shí),如果master分支的狀態(tài)沒有被更改過,即 bugfix分支的歷史記錄包含master分支所有的歷史記錄
所以通過把master分支的位置移動(dòng)到bugfix的最新分支上,就完成合并
如果master分支的歷史記錄在創(chuàng)建bugfix分支后又有新的提交,如下情況:
這時(shí)候使用git merge的時(shí)候,會(huì)生成一個(gè)新的提交,并且master分支的HEAD會(huì)移動(dòng)到新的分支上,如下:
從上面可以看到,會(huì)把兩個(gè)分支的最新快照以及二者最近的共同祖先進(jìn)行三方合并,合并的結(jié)果是生成一個(gè)新的快照
git rebase
同樣,master分支的歷史記錄在創(chuàng)建bugfix分支后又有新的提交,如下情況:
通過git rebase,會(huì)變成如下情況:
在移交過程中,如果發(fā)生沖突,需要修改各自的沖突,如下:
rebase之后,master的HEAD位置不變。因此,要合并master分支和bugfix分支
從上面可以看到,rebase會(huì)找到不同的分支的最近共同祖先,如上圖的B
然后對(duì)比當(dāng)前分支相對(duì)于該祖先的歷次提交,提取相應(yīng)的修改并存為臨時(shí)文件(老的提交X和Y也沒有被銷毀,只是簡(jiǎn)單地不能再被訪問或者使用)
然后將當(dāng)前分支指向目標(biāo)最新位置D, 然后將之前另存為臨時(shí)文件的修改依序應(yīng)用
三、區(qū)別
從上面可以看到,merge和rebasea都是合并歷史記錄,但是各自特性不同:
merge
通過merge合并分支會(huì)新增一個(gè)merge commit,然后將兩個(gè)分支的歷史聯(lián)系起來
其實(shí)是一種非破壞性的操作,對(duì)現(xiàn)有分支不會(huì)以任何方式被更改,但是會(huì)導(dǎo)致歷史記錄相對(duì)復(fù)雜
rebase
rebase會(huì)將整個(gè)分支移動(dòng)到另一個(gè)分支上,有效地整合了所有分支上的提交
主要的好處是歷史記錄更加清晰,是在原有提交的基礎(chǔ)上將差異內(nèi)容反映進(jìn)去,消除了 git merge所需的不必要的合并提交
參考文獻(xiàn)
https://zhuanlan.zhihu.com/p/361182707
https://yuweijun.github.io/git-zh/1-git-branching.html#_rebasing
https://backlog.com/git-tutorial/cn/stepup/stepup1_4.html