git工作流及遇到的問題
在介紹Git常用命令,現在就需要在工作中合理的使用這些命令,每個公司、每個團隊在工作中都會使用不同的工作流來開發,下面介紹了幾種我在工作中使用的工作流及遇到的些問題。
- 主幹開發
- git flow
- git 多環境工作
主幹開發
顧名思義,即僅僅就一個主幹分支,所有人都基於此分支開發,如下圖:
小百提交了C1、C3,大川提交了C2、C4,兩個人只要pull下代碼都會看到對方最新的提交。這裡僅僅就只有一個master分支,所有人都基於此分支開發
這種分支模型主要適用於:
1、開發團隊系統設計和開發能力強。有一套有效特性切換機制,保證上線無需改變代碼就能改變系統運行行為(比如:簡單修改一個配置即可),需要快速迭代,每個人都能立馬看到任何人提交的代碼。類似Google、Facebook都採用了這種主幹分支開發。
2、組件開發團隊,成員能力強,人員少,溝通順暢。用戶升級組件成本低的環境。
這種分支模型的缺點也很明顯,當有人提交了一些有bug的代碼,如果沒有配套的機制很容易影響線上的環境,對於大多數公司來說都不太適合。
git flow
git flow是Vincent Driessen提出的一套代碼管理規範流程,A Successful Git Branching Model,
如下圖:
這個圖咋一看,感覺比較難懂,因為它定義了太多分支(master、develop、feature、release、hotfix),如果你感覺看的很彆扭,可以把這張圖逆時針旋轉90度,或許更容易理解些。
我把這張圖拆解了下面幾個步驟,從項目最開始說起:
1、當最初在gitlab創建了一個項目,此時就只有一個master分支,注意這個master分支是不允許在上面修改代碼的,所以立馬需要拉一個develop分支,作為後面的開發分支。
2、有了develop分支,就可以進行開發了,比如:小百和大川兩個人同時接到了兩個需求,小百(登錄模塊開發)、大川(用戶註冊模塊),這時小百和大川需要基於develop各拉取一個分支,這兩個分支就是feature分支。
3、小百和大川兩個人都開發完畢了,需要提交代碼,一般是小百和大川把代碼提交到遠程,發送一個merge到develop請求,然後由專人審核沒問題,再合併到develop。
4、合到develop分支上的功能,可能會有bug,無法保證它的質量,所有基於develop會創建一個release分支,比如叫:release-1.0.0,然後由測試對release-1.0.0進行測試,測試通過了,同樣發送一個merge到master分支的請求。
5、上面的請求通過後,就表示1.0.0功能已完成,可以基於此打一個標籤叫:1.0.0-RELEASE,然後就可以發佈出去 了,看到這裡應該很熟悉了,因為你從maven下載包時,經常可以看到某個jar的命名是xxx.1.0.0-RELEASE。
6、對於master上1.0.0發佈的版本,可能後面又發現了bug,或者有需要優化的,這時就可以基於1.0.0-RELEASE拉取一個新分支:hotfix-1.0.0,待解決完成後直接合到master分支上,再打一個標籤叫:1.0.1-RELEASE,即對於1.0.0的補丁。
如果有新的功能需求,重新按照上面步驟開發,可以看到每次迭代都會產生很多分支,所以當一個功能正常上線穩定後,可以刪除對於的feature、release、hotfix分支。
這種分支模型適合有預定的發佈週期,需要執行嚴格的發佈流程的項目,現在很多公司基於此,比如去掉了hotfix、release分支,都是對於以上模型的變種。
git 多環境工作
多環境就是一個項目在它的開發中會部署到很多環境中,這種項目都是需要快速迭代和持續交互,其實也是git flow模型的一個變種,比如一個產品,它在每一個階段都會有新增和修改需求,我們暫且把三個月內的需求叫做day90,6個月的需求叫做day180,其中day90和day180都要單獨部署,避免測試之間干擾,如下圖:
最開始是基於develop拉取feature分支進行開發,合併到day90上進行測試,到一定階段後,需要安排day180的功能開發了,此時一般會從develop再拉取一個分支day180
上圖中還有兩個分支,沒畫出來,是day90-uat,day180-uat,即使day90和day180測試通過後,合併到對應分支上,給客戶演示的環境。
在day90和day180同時進行的過程中,有可能會需求變更,有可能會出現測試的bug,所以後期對於新功能的修復可以從day90或day180上拉取一個新的分支進行開發/修復,完成後再合併到各自分支。
注:這裡開發/修復完成同樣需要合併到develop環境,主要是為了開發人員自己能在開發環境上自測一遍,避免基本的流程有問題。
master分支為線上版本,只能等到uat分支上都確定沒有問題,再合併上去。
工作流中一些問題
1、怎樣命名自己的開發分支
比如上面多環境分支,如果小百需要基於day180開發一個新的功能(用戶登錄),一般可以命名:分支_作者_功能_時間,在day180上執行:
git checkout -b day180_hb_user_login_20200301
或者如果是修復bug,可以命名:分支_作者_bug說明_(bugId)_時間,如:
git checkout -b day90_hb_fix_user_register_bug_001_20200301
有個小技巧,當一段時間接到很多bug和新需求,會產生很多分支,可能到後面自己都忘記哪個分支已經合併了,所以如果你已經合併了一個分支,可以把分支後面加一個後綴,比如:
git branch -m day180_hb_user_login_20200301 day180_hb_user_login_20200301_had_merge
確認沒有問題後,再刪除對應的分支。
2、哪些情況文件會產生衝突
不會衝突的情況:
- 兩個人同時修改了不同的文件
- 兩個人修改了同一個文件不同的區域
- 一個人重命名了文件名
會衝突的情況
- 兩個人同時修改了同一個文件相同的區域
- 兩個人同時重命名了同一個文件名
3、在集成分支慎用git push -f命令
在開發時,經常會遇到,有一個功能已經開發完成了,已經合到master了,準備上線,突然發現了bug,需要立即回滾,有人可能會使用下面命令:
git reset --hard 回退的版本
但如果你現在使用git push,肯定會報錯,因為你本地的分支落後於遠程分支,你可能會直接使用:
git push -f origin day90
這樣操作後,你本地的記錄會完全覆蓋遠程的記錄,回退版本之後的記錄也會完全消失,後面有人修改了一些代碼也會被你全部覆蓋,所以在團隊協作儘量不使用這個命令,除非你清楚知道不會產生任何影響或者需要這麼做。
但這樣操作後,你本地的記錄會完全覆蓋遠程的記錄,回退版本之後的記錄也會完全消失,後面有人修改了一些代碼也會被你全部覆蓋,所以在團隊協作儘量不使用這個命令,除非你清楚知道不會產生任何影響或者需要這麼做。
正確的方式是使用revert,revert不會刪除歷史記錄,只會重新生成一個新的版本,如下圖(回退“添加公用配置文件”這個版本):
使用:git revert 回退之後:
git revert 3c838ea
4、合併多個歷史的commit
如果你在開發過程中,涉及到多個提交,,但其實這幾個提交的功能都是一樣的,需要想要合併成一個提交,如下,我需要合併兩次新增ftl文件
可以找到第一次新增ftl的父節點提交,使用:
git rebase -i
會出現如下界面,可以看到下面介紹了一些常用的命令
修改為
表示把ece332f提交合併到7fbc773中,wq!保存退出,會彈出:
修改兩次提交的註釋,然後wq!保存退出,使用:git log查看日誌
如果是想要把多次不同間隔的提交合並呢,方法也同理,比如把兩次修改readme合併,找到第一次修改readme的父節點9f1dbb1
git rebase -i 9f1dbb1
5、多人開發的分支需要一起聯調
在開發中大多數情況雖然每個人都負責不同的模塊,在開發中大多數情況雖然每個人都負責不同的模塊,但是經常會出現兩個人一起聯調的情況,比如小百和大川分別開發用戶登錄和用戶註冊模塊
小百在自己的分支上添加了一個公用的文件,而大川需要這個公用文件才能繼續開發,如下圖:
如果對於這個公用文件,有提交記錄,大川可以直接在自己的分支上cherry-pick這個提交
git fetch #獲取遠程倉庫的所有更新的分支
git cherry-pick
如果這個公用文件,沒有提交記錄,大川可以在自己的分支上只checkout這個文件到自己的分支
git checkout xiaobai_user_login_20200303 common.js
當然大川也可以直接使用merge命令把小白的代碼都合並過去
git merge xiaobai_user_login_20200303
注意使用merge命令的時候不要把一些不同週期上線的代碼也合並過去了
比如小百開發了註冊模塊,還開發了一個角色模塊,小百把這兩個功能都放到xiaobai_user_login_20200303分支上開發了
現在需要用戶登錄模塊和用戶註冊模塊先提交測試,角色模塊放後面處理
這種情況,如果大川需要合併小百分支上登錄模塊,可以使用上面的cherry-pick所有提交或chekout一個個文件的來合併。
在開發中如果確定幾個功能會放在不同的時間點上線,或者一個模塊開發週期比較長,或者別人要用到,最好單獨搞一個分支。