疫情期間我感受整我的懶散了很多,慢慢有意識要振做起來了,恢復到正常的節奏。最近團隊代碼庫從Gerrit
遷移到了Gitlab
,爲了讓前端團隊平常開發工做有條不紊,高效運轉,開發歷史可追溯,我也查閱和學習了很多資料。參考業界主流的Git工做流,結合公司業務特質,我也梳理了一套適合本身團隊的Git工做流,在這裏作下分享。前端
首先要說的是分支管理,分支管理是git
工做流的基礎,好的分支設計有助於規範開發流程,也是CI/CD
的基礎。git
業界主流的git
工做流,通常會分爲develop
, release
, master
, hotfix/xxx
, feature/xxx
等分支。各個分支各司其職,貫穿了整個開發,測試,部署流程。我這裏也基於主流的分支策略作了一些定製,下面用一張表格簡單歸納下:shell
分支名 | 分支定位 | 描述 | 權限控制 |
---|---|---|---|
develop | 開發分支 | 不能夠在develop分支push代碼,應新建feature/xxx進行需求開發。迭代功能開發完成後的代碼都會merge到develop分支。 | Develper不可直接push,可發起merge request |
feature/xxx | 特性分支 | 針對每一項需求,新建feature分支,如feature/user_login,用於開發用戶登陸功能。 | Develper可直接push |
release | 提測分支 | 由develop分支合入release分支。ps: 應配置此分支觸發CI/CD,部署至測試環境。 | Maintainer可發起merge request |
bug/xxx | 缺陷分支 | 提測後發現的bug,應基於develop 分支建立bug/xxx 分支修復缺陷,修改完畢後應合入develop分支等待迴歸測試。 |
|
master | 發佈分支 | master應處於隨時可發佈的狀態,用於對外發布正式版本。ps: 應配置此分支觸發CI/CD,部署至生產環境。 | Maintainer可發起merge request |
hotfix/xxx | 熱修復分支 | 處理線上最新版本出現的bug | Develper可直接push |
fix/xxx | 舊版本修復分支 | 處理線上舊版本的bug | Develper可直接push |
通常來講,develop
, release
, master
分支是必備的。而feature/xxx
, bug/xxx
, hotfix/xxx
, fix/xxx
等分支純屬一種語義化的分支命名,若是要簡單粗暴一點,這些分支能夠不分類,都命名爲issue/issue號
,好比issue/1
,可是要在issue
中說明具體問題和待辦事項,保證開發工做可追溯。npm
利用Protected Branches
,咱們能夠防止開發人員錯誤地將代碼push
到某些分支。對於普通開發人員,咱們僅對develop
分支提供merge
權限。json
具體操做案例請前往下面的實戰案例一節查看。併發
咱們團隊採用的敏捷開發協做平臺是騰訊的TAPD,平常迭代需求,缺陷等都會在TAPD
上記錄。爲了讓Gitlab
代碼庫能與迭代平常事務關聯上,我決定用Gitlab issues
來作記錄,方便追溯問題。ide
里程碑Milestone能夠認爲是一個階段性的目標,好比是一輪迭代計劃。里程碑能夠設定時間範圍,用來約束和提醒開發人員。gitlab
里程碑能夠拆解爲N個issue,新建issue
時能夠關聯里程碑。好比這輪迭代一共5個需求,那麼就能夠新建5個issue
。在約定的時間範圍內,若是一個里程碑關聯的全部issue
都Closed
掉了,就意味着目標順利達成。post
Gitlab
提供了label
來標識和分類issue
,我以爲這是一個很是好的功能。我這裏列舉了幾種label
,用來標識issue
的分類和緊急程度。單元測試
全部的開發工做應該經過issue
記錄,包括但不限於需求,缺陷,開發自測試,用戶體驗等範疇。
這裏大概又分爲兩種狀況,一種是TAPD
記錄在案的需求和缺陷,另外一種是與產品或測試人員口頭溝通時傳達的簡單需求或缺陷(小公司會有這種狀況...)。
對於TAPD
記錄的需求和缺陷,建立issue
時應附上連接,方便查閱(上文中已有提到)。
對於口頭溝通的需求和缺陷,我定了個規則,要求提出人本人在Gitlab
上建立issue
,並將需求或缺陷簡單描述清楚,不然口頭溝通的開發工做我不接(也是爲了不過後扯皮)。
ps:其實要求產品或者測試提issue
,還不如上Tapd
記錄。我定這麼個規則,其實就是借Gitlab
找個說辭,杜絕口頭類需求或缺陷,哈哈。
開發者本身發現了系統缺陷或問題,此時應該經過issue
記錄問題,並建立相應分支修改代碼。
我前面也說了,個人原則是issue
驅動開發工做。
下面用幾個例子來簡單說明基本的開發流程。小公司裏整個流程比較簡單,沒有複雜的集成測試,多輪驗收測試,灰度測試等。我甚至連單元測試都沒作(捂臉...)。
公共庫和公共組件實際上是頗有必要作單元測試的,這裏立個flag,後面必定補上單元測試。
feature/1,一個特性分支,對應issue 1
正常的需求固然來源於產品經理等需求提出方,因爲是經過示例說明,這裏我本身在TAPD
上模擬着寫一個需求。
建立Gitlab issue
,連接到TAPD
中的相關需求。
基於develop
分支建立feature
分支進行功能開發(要保證本地git倉庫當前處於develop分支,且與遠程倉庫develop分支同步)。
git checkout -b feature/1
或者直接以遠程倉庫的develop
分支爲基礎建立分支。
git checkout -b feature/1 origin/develop
ps:我這裏用的feature/1
做爲分支名,其實這裏的1
是用的issue
號,並無用諸如feature/login_verify
之類的名字,是由於我以爲用issue
號能夠更方便地找到對應的issue
,更容易追蹤代碼。
接着咱們開始開發新功能......
完成功能開發後,咱們須要提交代碼並同步到遠程倉庫。
PS D:\projects\gitlab\project_xxx> git add . PS D:\projects\gitlab\project_xxx> git cz cz-cli@4.0.3, cz-conventional-changelog@3.1.0 ? Select the type of change that you're committing: feat: A new feature ? What is the scope of this change (e.g. component or file name): (press enter to skip) ? Write a short, imperative tense description of the change (max 94 chars): (9) 登陸校驗功能 ? Provide a longer description of the change: (press enter to skip) ? Are there any breaking changes? No ? Does this change affect any open issues? Yes ? If issues are closed, the commit requires a body. Please enter a longer description of the commit itself: - ? Add issue references (e.g. "fix #123", "re #123".): fix #1 git push origin HEAD
git cz
是利用了commitizen
來替代git commit
。詳情請點擊前端自動化部署的深度實踐深刻了解。
fix #1
用於關閉issue 1
。
git push origin HEAD
則表明推送到遠程倉庫同名分支。
開發人員發起Merge Request
,請求將本身開發的功能特性合入develop
分支。
接着Maintainer
須要Review代碼,確認無誤後贊成Merge。而後這部分代碼就在遠程Git
倉庫入庫了,其餘開發同窗拉取develop
分支就能看到了。
issue/2,處理更新日誌,版本號等內容,對應issue 2
每一個團隊的開發節奏都不一樣,有的團隊會每日持續集成發版本提測,有的可能兩天一次,這個就不深刻討論了......
那麼當咱們準備提測時,應該怎麼作呢?
經過上節的瞭解,咱們已經知道,迭代內的功能需求都會經過feature/xxx
分支合入到develop
分支。
提測前,通常來講,仍是要更新下CHANGELOG.md
和package.json
的版本號,能夠由Maintainer
或其餘負責該項事務的同窗執行。
主要是執行npm version major/minor/patch -m 'something done',具體操做能夠參考 前端自動化部署的深度實踐一文。
git checkout -b issue/2 origin/develop npm version minor -m '迭代1第一次提測' git push origin HEAD 而後發起merge request合入develop分支
此時,應以最新的develop
分支代碼在開發環境跑一遍功能,保證版本自測經過。
提測時,由Maintainer
發起Merge Request
,將develop
分支代碼合入release
分支,此時自動觸發Gitlab CI/CD
,自動構建併發布至測試環境。
版本提測後,各責任人應在TAPD
上將相關需求和缺陷的狀態變動爲「測試中」。
bug/3,一個bug分支,對應issue 3
這裏說的是在迭代週期內由測試工程師發現的測試環境中的系統bug
,這些bug
會被記錄在敏捷開發協做平臺TAPD
上。修復測試環境bug
的步驟與開發需求相似,這裏簡單說下步驟:
在Gitlab上建立issue
建立issue,並附上TAPD上的缺陷連接,方便追溯
建立分支&修復缺陷
基於develop
分支建立分支:
// 3是issue號 git checkout -b bug/3 origin/develop
接着改代碼......
commit & push
PS D:\projects\gitlab\project_xxx> git cz cz-cli@4.0.3, cz-conventional-changelog@3.1.0 ? Select the type of change that you're committing: fix: A bug fix ? What is the scope of this change (e.g. component or file name): (press enter to skip) ? Write a short, imperative tense description of the change (max 95 chars): (11) 修復一個測試環境bug ? Provide a longer description of the change: (press enter to skip) ? Are there any breaking changes? No ? Does this change affect any open issues? Yes ? If issues are closed, the commit requires a body. Please enter a longer description of the commit itself: - ? Add issue references (e.g. "fix #123", "re #123".): fix #3 git push origin HEAD
開發人員發起Merge Request
,請求將本身修復缺陷引入的代碼合入develop
分支。
而後Maintainer
須要Review代碼,贊成本次Merge Request
。
該bug
將在下一次CI/CD
後,進入迴歸測試流程。
若是是級別很高的bug
,好比影響了系統運行,致使測試人員沒法正常測試的,應以release
分支爲基礎建立bug
分支,修改完畢後合入release
分支,再發起cherry pick
合入develop
分支。
通過幾輪持續集成和迴歸測試後,一個迭代版本也慢慢趨於穩定,此時也迎來了激動人心的上線時間。咱們要作的就是把經過了測試的release
分支合入master
分支。
這一步相對簡單,可是要特別注意權限控制(防止生產環境事故),具體權限控制能夠回頭看第一章節分支管理。
與release
分支相似,master
分支自動觸發Gitlab CI/CD
,自動構建併發布至生產環境。
revert/4,一個回滾分支,對應issue 4
代碼升級到線上,可是發現報錯,系統沒法正常運行。此時若是不能及時排查出問題,那麼只能先進行版本回退操做。
先說說慣性思惟下,個人版本回退作法。
首先仍是建立issue
記錄下:
基於master
分支建立revert/4
分支
git checkout -b revert/4 origin/master
假設當前版本是1.1.0
,咱們想回退到上個版本1.0.3
。那麼咱們須要先查看下1.0.3
版本的信息。
PS D:\tusi\projects\gitlab\projectname> git show 1.0.3 commit 90c9170a499c2c5f8f8cf4e97fc49a91d714be50 (tag: 1.0.3, fix/1.0.2_has_bug) Author: tusi <tusi@xxx.com.cn> Date: Thu Feb 20 13:29:31 2020 +0800 fix:1.0.2 diff --git a/README.md b/README.md index ac831d0..2ee623b 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ 只想修改舊版本的bug,不改最新的master +1.0.2版本仍是有個版本,再修復下 + 特性2提交 特性3提交
主要是取到1.0.3
版本對應的commit id
,其值爲90c9170a499c2c5f8f8cf4e97fc49a91d714be50
。
接着,咱們根據commit id
進行reset
操做,再推送到遠程同名分支。
git reset --hard 90c9170a499c2c5f8f8cf4e97fc49a91d714be50 git push origin HEAD
接着發起Merge Request
把revert/4
分支合入master
分支。
通常來講,這波操做沒什麼問題,能解決常規的回滾問題。
因爲master
分支是保護分支,設置了不可push
。若是不想經過merge
的方式回滾,因此只能先臨時設置Maintainer
擁有push
權限,而後由Maintainer
進行回滾操做。
git checkout master git pull git show 1.0.3 git reset --hard 90c9170a499c2c5f8f8cf4e97fc49a91d714be50 git push origin HEAD
完過後,還須要記得把master
設置爲不可push
。
Q: 爲何不讓Maintainer
一直擁有master
的push
權限?A: 主要仍是爲了防止出現生產環境事故,給予臨時性權限更穩妥!
如題,git reset --hard
確實是存在問題的。git reset --hard
屬於霸道玩法,直接移動HEAD
指針,會丟棄以後的提交記錄,若是不慎誤操做了也別慌,仍是能夠經過查詢git reflog
找到commitId
搶救回來的;git reset
後還存在一個隱性的問題,若是與舊的branch
進行merge
操做時,會把git reset
回滾的代碼從新引入。那麼怎麼解決這些問題呢?
別慌,這個時候你必須掏出git revert
了。
Q:git revert
的優點在哪?A: 首先,
git revert
是經過一次新的commit來進行回滾操做的,HEAD指針向前移動,這樣就不會丟失記錄;另外,git revert
也不會引發merge
舊分支時誤引入回滾的代碼。最重要的是,git revert
在回滾的細節控制上更加優秀,可解決部分回滾的需求。
舉個栗子,本輪迭代團隊共完成需求2
項,而上線後發現其中1
項需求有致命性缺陷,須要回滾這個需求相關的代碼,同時要保留另外一個需求的代碼。
首先咱們查看下日誌,找下這兩個需求的commitId
PS D:\tusi\projects\test\git_test> git log --oneline 86252da (HEAD -> master, origin/master, origin/HEAD) 解決衝突 e3cef4e (origin/release, release) Merge branch 'develop' into 'release' f247f38 (origin/develop, develop) 需求2 89502c2 需求1
咱們利用git revert
回滾需求1相關的代碼
git revert -n 89502c2
這時可能要解決衝突,解決完衝突後就能夠push
到遠程master
分支了。
git add . git commit -m '回滾需求1的相關代碼,並解決衝突' git push origin master
感受仍是菜菜的,若是大佬們有更優雅的解決方案,求指導啊!
hotfix/5,一個線上熱修復分支,對應issue 5
好比線上出現了系統沒法登陸的bug
,測試工程師也在TAPD
提交了缺陷記錄。那麼修復線上bug
的步驟是什麼呢?
issue
,標題能夠從TAPD
中的Bug
單中copy
過來,而描述就貼上Bug
單的連接便可。基於master
分支建立分支hotfix/5
。
git checkout -b hotfix/5 origin/master
修復完此bug
後,提交該分支代碼到遠程倉庫同名分支
git push origin HEAD
cherry pick
合入到master
和develop
分支,並在master
分支打上新的版本tag
(假設當前最大的tag
是1.0.0
,那麼新的版本tag
應爲1.0.1
)。fix/6,一個線上舊版本修復分支,對應issue 6
某些項目產品可能會有多個線上版本同時在運行,那麼不可避免要解決舊版本的bug
。針對線上舊版本出現的bug
,修復步驟與上節相似。
issue
,描述清楚問題假設當前版本是1.0.0
,而0.9.0
版本出了一個bug
,應基於tag 0.9.0
建立fix
分支。
git checkout -b fix/6 0.9.0
修復缺陷後,應打上新的tag 0.9.1
,並推送到遠程。
git tag 0.9.1 git push origin tag 0.9.1
bug
也存在於最新的master
分支,則須要git push origin HEAD
提交該fix
分支代碼到遠程倉庫同名分支,而後發起cherry pick
合入到master
,此時很大可能存在衝突,須要解決衝突。在瞭解到cherry pick
以前,我一直認爲只有git merge
能夠合併代碼,也好幾回遇到合入了不想要的代碼的問題。有了cherry pick
,咱們就能夠合併單次提交記錄,解決git merge
時合併太多不想要的內容的煩惱,在解決bug
時特別有用。
通過這段時間的使用,我發現使用git merge
合併分支時,會讓git log
的Graph
圖看起來有點吃力。
PS D:\tusi\projects\gitlab\projectname> git log --pretty --oneline --graph * 7f513b0 (HEAD -> develop) Merge branch 'issue/55' into 'release' |\ | * 1c94437 (origin/issue/55, issue/55) fix: 【bug】XXX1 | * c84edd6 Merge branch 'release' of host:project_repository into release | |\ | |/ |/| * | 115a26c Merge branch 'develop' into 'release' |\ \ | * \ 60d7de6 Merge branch 'issue/30' into 'develop' | |\ \ | | * | 27c59e8 (origin/issue/30, issue/30) fix: 【bug】XXX2 | | | * ea17250 Merge branch 'release' of host:project_repository into release | | | |\ | |_|_|/ |/| | | * | | | 9fd704b Merge branch 'develop' into 'release' |\ \ \ \ | |/ / / | * | | a774d26 Merge branch 'issue/30' into 'develop' | |\ \ \ | | |/ /
接着我就瞭解到了git rebase
,變基,哈哈哈。因爲對rebase
瞭解不深,目前也不敢輕易改用rebase
,畢竟rebase
仍是有不少隱藏的坑的,使用起來要慎重!在這裏先挖個坑吧,後面搞懂了再填坑......
Merge Request
必須由別的同事Review
並贊成合入,這樣更有利於發現代碼問題。TAPD
還支持與Gitlab
協同的。詳情見源碼關聯指引。實踐證實,這套Git
工做流目前能覆蓋我項目開發過程當中的絕大部分場景。不過要注意的是,適合本身的纔是最好的,盲目採用別人的方案有時候是會水土不服的。
以上所述純屬前端小微團隊內部的Gitlab
實踐,必然存在着不少不足之處,若有錯誤之處還請指正,歡迎交流。