git 多人在同一分支上迭代開發時,如何保證分支提交歷史保持線性

背景

最近我們組幾個同事都投入到了一個新項目,互相之間的功能耦合比較緊密,因此,是打算從master上新拉一個分支,可以理解爲我們幾個人的開發分支,以develop代替。

一開始,我們是打算像svn那樣用的,幾個人就把這個新分支develop當做唯一的主幹分支,幾個人互相快速提交/拉取,回到了用svn的快樂日子。

不過,大家用svn也知道,經常呢,我們爲了保證代碼不丟,會經常性地往分支提交,即使某個功能寫了一半,一個功能,n次commit記錄,且和同事的commit交錯在一起;另外,我們提交的代碼,有時候會導致同事那裏跑不起來。

簡而言之,就是commit有點碎;另外,可能阻塞其他同事。

我們組長提了另外一種思路,就是,每個人基於這個開發分支develop,再自己單獨拉取一個分支出來,如develop-zhangsan,develop-lisi。每個人在自己的單獨的分支上開發,開發了一個較爲完整的功能後,再提一個pull request給develop,此時,可以對這個較完整的功能做代碼review,review通過後,即合併到develop分支。但此時,怎麼纔是最佳實踐呢,且能保證開發分支develop的提交歷史成爲優雅的一條線呢?

這裏假設有張三、李四兩個人,基於gitlab、github、gitee等進行開發,最終,主要有以下幾個分支:

遠程 本地
origin/master master
origin/develop develop
origin/develop-zhangsan develop-zhangsan
origin/develop-lisi develop-lisi

實戰環境準備

我這邊已經準備好了實戰案例,已經把上面的幾個分支都拉好了。

https://gitee.com/ckl111/git-rebase-test

假設我先在遠程,把這幾個分支先建好,我是在gitee操作的。

目前,zhangsan、lisi分支,是基於develop拉出來的,所以最新提交都是一樣的。

模擬張三開發

大家看上圖,張三來了一頓操作,切到了自己的分支,改了點東西,做了一次提交,不過提交還沒推送到遠端自己的分支。

模擬李四開發

修改、推送

李四也是個猛人啊,上來一頓cv,commit、push一氣呵成。

遠端狀態

此時,可以看到,遠端分支裏,只有lisi這娃兒的分支狀態有變化。此時,按照標準流程,李四需要在遠程發起一個到develop的pull request。

發起pr

此時,是可以查看這次pr的內容,包括提交內容,文件修改差異。具體每個平臺不一樣,但是功能應該類似。

此時,假設經過代碼review,認爲沒有問題,那麼可以合併到develop去了。

合併後,develop的情況

可以看到,除了把lisi分支的commit拿過來了,還加了個表示本次合併的commit。

ok,李四的工作,第一階段就算結束了。

模擬張三拉取李四代碼

張三一看,李四這小夥子太快了,cv666。假設張三就依賴李四代碼,此時,應該要把李四代碼拉下來。

其實,這裏有個操作上的問題,當前張三在自己的分支上,他現在需要做的是:拉取develop代碼最新代碼,然後將develop的代碼合到自己這裏來。

這個步驟的話,其實有些工具做得比較好,我用的intelj idea就有相關功能。這一步如果工具不趁手的話,非常要命。因爲我們可能開發到一半,要去切換到其他分支,結果本分支有代碼沒提交,還得先提交或者stash,切過去到develop,pull最新代碼。然後再切回來自己分支。

很累人。

這塊回頭我講講idea裏面的實戰操作,其他ide工具大家可以自行探索。

這次先只介紹命令行版本,我先用笨辦法,切過去,pull,再切回來的方式吧。

模擬張三合併/rebase李四代碼

要保證develop的commit保持線性,這裏有個重點,我們要以rebase的方式去合併develop的代碼,而不是merge的方式。

rebase呢,這裏簡單說下,

這裏就是rebase的大體流程圖,其實,我剛有個想法,最近拿起了以前的電視劇,新三國。裏面呂布不就換了幾位義父嗎,這裏的rebase,換的也是parent啊,感覺rebase也是相當神似。

當然了,忘了一點,進行rebase那些的commit,hashcode會發生變化,和以前不一樣了。

我們這邊實際操作,看看效果:

這裏主要幾個操作,

1 git rebase develop -------因爲和lisi改了同一行,需要解決衝突
2 我這邊習慣用小烏龜git,解決衝突
3 git add .
4 git rebase --continue

形象一點,也就是前面那個圖,不過新的rebase後的commit的hash變了

模擬張三push代碼到遠端,遠端發起pull request

push

pull req

遠端develop log查看

可以看看,遠程的develop分支,log是非常好看的。

第二輪開始

可以看到,第一輪已經差不多結束了,張三李四各提交了一次。假設現在輪到李四了,李四發現張三有push代碼,就準備拉下來,就像之前的張三一樣。

李四切換到develop,拉取最新develop代碼,並rebase

然後,我們基於develop,進行rebase(也就是,以develop爲base)。本來爲了模擬效果,是應該先本地搞點提交,再rebase的,我搞忘了。不過不重要,過程和前面張三差不多。

李四修改代碼、commit、push

李四遠端發起pull request

檢查遠程develop分支的commit 記錄

依然是漂亮的commit記錄。

張三在此期間,已經做了修改、commit、push

張三這期間,暫時不依賴李四代碼,就自己commit、push了(爲啥push,怕代碼丟嘛,多個備份)

張三切換到develop、拉取最新develop、rebase

張三此時終於準備合併李四的代碼。

省略了張三這次解決了衝突的過程,我依然用了小烏龜。

張三此時的log情況

張三,由於rebase,導致自己本地之前的那次commit,被rebase了。rebase後,hashcode也變了。

此時,張三的本地分支,和張三遠程分支之間,出現了分叉。

張三rebase後,面臨分叉,強行push,覆蓋遠程分支

強制push後,張三遠程分支的log

張三遠程發起pull request

遠程develop分支log,線性日誌

總結

兩輪實戰結束。大家學會了沒?

2點要點:

1、總是rebase的方式去合併develop分支

2、rebase的時候,就是會面臨分叉的情況,此時強制push遠程分支,讓遠程分支的log和本地一致。(強制push適用於文章中的情況:每個人有自己的分支,不會有其他人用。一旦涉及多人共用一個分支,就彆強制push了,不然要打架)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章