如何構建基於Git的開發工作流規範?Git版本管理工具應該這樣用
- 2019 年 10 月 4 日
- 筆記
轉載自:https://github.com/GDJiaMi/frontend-standards/blob/master/development.md
Git 分支模型
master分支
master分支表示一個穩定的發佈版本. 對應GZB的大版本.
- 場景: 前端應用會跟隨工作寶版本迭代, 在dev分支測試穩定後, 會合併到master分支, 並使用tag標記應用版本和對應的工作寶版本
- tag規範:
v{APP_version}@{GZB_version}
, 例如v0.1.0@GZB_6.6 - 人員: 由項目負責人進行審核合併, 普通開發者沒有權限
dev分支
開發者主要工作的分支, 最新的特性或bug修復都會提交到這個分支. 開發者如果在該分支進行了提交,在push到遠程之前應該先pull一下, 並盡量使用rebase模式,保證分支的簡潔
- 命名規範: dev
- tag規範: 在dev分支中也可能會經歷發佈過程, 例如bug修復版本. 這裡同樣使用tag來標記這些發佈. 例如v0.1.1
- 提交規範:如果實在開發分支上進行開發,在推送到遠程之前,應該使用
git rebase
形式更新本地分支。
feature分支
涉及多人協作或者大功能的開發, 應該從dev分支checkout出獨立的feature分支, 避免干擾dev分支
- 場景:
- 涉及多人協作: 團隊多個成員在同一個項目下負責開發不同的功能, 這時候每個成員在自己的feature分支獨立開發
- 大功能開發: 大功能開發跨越周期比較長, 需要多次迭代才會穩定. 這時候應該在獨立的分支上開發. 方便跟蹤歷史記錄, 也免於干擾dev分支的迭代和發佈
- 命名規範
- feature/name: name是功能名稱
- feature/GZB_version: 這也是團隊常見的模式, 當無法使用一個功能名稱來描述時, 可以使用GZB版本號作為』功能』
- 合併時機
- 當feature分支迭代穩定, 並通過測試後, 合併到dev分支. 合併到dev後, feature分支的生命周期就結束了. 後續bug修復和功能優化直接在dev開發
- 當多個feature分支需要合併對外發佈臨時版本時. 合併到preview分支 . ⚠️這種情況不應該合併到dev分支, 因為feature分支可能還不穩定或未完成. 比如為了聯調某些功能.
- 合併方式
- 不要使用fast-forward. 這樣可以在分支圖上查看到分支歷史
preview分支
臨時的預覽分支, preview分支用於臨時合併feature分支, 這其中可能會修復某些bug或者衝突. 可以選擇性地將這些提交cherrypick回feature分支. 當預覽結束後就可以銷毀preview分支
release分支
release分支有兩種使用策略,第一種遵循gitFlow
流程, 第二種是目前後端團隊使用的策略,為了配合後端工作,我們主要使用第二種
git flow 風格的release分支
當前前端應用的穩定版本和GZB版本綁定. release分支不一定存在, 一般情況下, 只會在前端版本穩定後, 將其合併到master, 並創建tag標記. 而只有需要為指定的正式版本修復bug時才會創建release分支
- 場景: 需要為某個正式版本修復bug(hotFix)時, 從master的對應tag中checkout release分支
- 命名規範:
release/{GZB_version}
外部人員只會關注GZB版本 - 如何修復
- 如果對應bug可以在dev分支直接被修復, 可以先提交到dev分支(或者已經修復了), 然後再cherrypick到release分支
- 如果bug在新版本無法復現. 比如新版本升級了依賴. 那麼在release分支直接修復即可
自定義風格release分支
當要發佈一個工作寶對應的版本時(或者一開始開發時)從dev分支checkout出一個開發分支,後續需要對外發佈時,將dev分支合併到release分支, 並打上版本tag. 後面會介紹到後端開發和自動交付機制這種分支模式。
這一種使用策略. gzb後端在使用, 為了配合後端工作, 我們也推薦使用這種方式
- 何時創建:
- 開啟GZB新版本開發任務時(推薦)
- 向外發佈第一個版本時
- 何時合併:後面dev有版本發佈都要合併到release分支,直到開啟另一條release分支
- 好處
- 對發佈內容進行篩選
- 專門用於發佈, 開發者容易過濾變更的內容
提交信息規範
一個好的提交信息, 會幫助你提高項目的整體質量.
- why
- 格式統一的提交信息可以幫助自動化生成changelog
- 版本庫不只是存放代碼的倉庫, 也記錄項目的開發記錄. 這些記錄應該可以幫助後來者快速地學習和回顧代碼. 也應該方便其他協作者review你的代碼
- 原則: 半年後, 你能看懂你的commit做了什麼東西
- 方式: 使用git commit(打開編輯器)而不是git commit -m
- 必要信息
- 說明變動功能的細節。一個提交不應該做超過2個功能的變動
- 問題是什麼導致的?
- 簡短說明使用什麼方式, 策略, 修復了問題.
- 提交改變了什麼, 讓其他reviewer更容易審核代碼和忽略無關的改變
- 為什麼進行這次提交?
- 如何解決的問題?
- 變化可能影響哪些地方
格式
我們採用angular的提交規範, 在這個規範的基礎上支持(可選)emoji
進行修飾
<type>(<scope>): <subject> <body> <footer>
header
如果提交時feature或者fix(已發佈的版本), 這些提交信息應該出現在CHANGELOG
- type: 說明commit的類別. 可以配合emoji使用, 讓閱讀者更快地區分提交的類型,允許以下類型:
- git revert 命令用於撤銷之前的一個提交, 並在為這個撤銷操作生成一個提交
- ✨feature或feat: 引入新功能
- ?fix: 修復了bug
- ?docs: 文檔
- ?style: 優化項目結構或者代碼格式
- ♻️refactor: 代碼重構. 代碼重構不涉及新功能和bug修復. 不應該影響原有功能, 包括對外暴露的接口
- ✅test: 增加測試
- ⏫chore: 構建過程, 輔助工具升級. 如升級依賴, 升級構建工具
- ⚡️perf: 性能優化
- ⏪ revert: revert之前的commit
- ? build或release: 構建或發佈版本
- ? safe: 修復安全問題
- scope: 可選. 說明提交影響的範圍. 例如樣式, 後端接口, 邏輯層等等
- Subject: 提交目的的簡短描述, 動詞開頭, 不超過80個字符. 不要為了提交而提交
body
可選. 對本次提交的詳細描述. 如果變動很簡單, 可以省略
footer
可選. 只用於說明不兼容變動(break change)和關閉 Issue(如果使用使用gitlab或github管理bug的話)
模板和示例
# 50-character subject line # # 72-character wrapped longer description. This should answer: # # * Why was this change necessary? # * How does it address the problem? # * Are there any side effects? # # Include a link to the ticket, if any.
參考vue, angular等開源庫項目的提交
BUG 處理規則
對於測試,目前會經歷兩個階段
- 冒煙測試:在對測試正式發版之前會要求對代碼進行自測,及冒煙測試。
- 正式測試階段:正式測試階段測試人員會在RDMS進行bug提交和管理,對BUG的處理規則如下:
- [解決待關閉]: 修改了程序代碼, 問題解決;
- [不做處理]: 沒有修改程序代碼, 是由於其他原因(需求變更等), 而解決的問題;
- [退回]: 無規律或只出現一次的BUG, 研發沒找到原因, 加上必要排查日誌後, 可退回給測試; 復現後重新打開
- [正在處理]: 已大致定位原因, 需要較多時間處理的BUG, 可置為"正在處理"
BUG的數量可能會和個人的KPI掛鈎。所以要謹慎自測
如何處理定製化需求
- 痛點
- 更新問題
- 每次正規代碼更新都要合併到該分支. 當分支較多時分支圖就會比較混亂
- 正規代碼合併是必然會帶來風險的, 比如項目結構變動, 依賴庫變動. 都可能導致定製化的代碼失效
- 對於定製化需求, 並不會引入到正規的代碼流中, 一般情況下會checkout出一個分支, 來專門做這裡定製化需求, 然後單獨發版. 使用分支模式的缺點有:
- 解決辦法
- 有些場景確實無法通過代碼層面解決, 比如ios應用定製啟動圖, icon, 應用名稱, 外觀等等. 這種方式優先使用fork模式, fork模式和分支模式沒本質區別, 但是至少可以避免干擾正規開發流程
- 例如通過權限系統來配置. 通過後端接口動態配置
- 盡量將定製化需求模塊化, 最小化和正規代碼之間的接觸面. 這是解決該問題最根本的方式.
- 檢驗方式是結構變化時, 沒有或很少適配代碼
- 減少代碼耦合
- 考慮通過代碼層面區分
- 優先使用fork模式
發佈工作流
- 流程
- 如果沒通過就打tag, 一旦出現測試失敗, tag就得重新打
- 進行代碼變更
- 提交這些變更, 進行CI讓這些變更通過測試
- 提升package.json的版本號, 更新CHANGELOG.md
- 打上tag, 提交
- 可選. 合併到release分支
- 工具
- 使用jm-deploy release自動化發佈並生成CHANGELOG.md
持續集成
前端項目基於公司內部部署的gitlab-ci來進行持續部署。包含以下階段(stage):
持續集成階段
- 檢查:包括單元測試和代碼lint。
- 所有push到版本庫的代碼都會跑這個階段. 可以在提交title中包含
[ci skip]
來跳過這個階段
- 所有push到版本庫的代碼都會跑這個階段. 可以在提交title中包含
- 構建: 對前端項目進行構建.
- 只有打上版本tag的提交或release分支會跑構建任務
- 發佈: 將前端的構建結果進行交付/發佈
- 只有打上版本tag的提交或者release分支會跑發佈任務. 詳見jm-deploy
版本類型
根據交付或部署的環境, 可以分為以下類型:
- preview: 臨時版本. 用於預覽和調試. 主要在聯調環境使用. 形式為:
v{VERSION}-preview
- test 可交付版本. 這個版本用於交付到stage或者測試環境. 形式為:
v{VERSION}
- production 生產版本. 表示實際部署到生產環境的版本. 如果test版本測試通過, 就會成為生產版本. 這個過程是通過將dev分支合併到master分支時實現的. 形式為:
v{VERSION}@{GZB_VERSION}
在實際開發中,可能不會嚴格區分這些版本,而是項目一開始就會有一個release分支,在這個release分支里進行發佈
交付
目前前端資源是跟隨後端Jar/War包一起部署的,通過將構建結果推送到一個』git發佈版本庫』的形式實現.
why
由於公司ToB業務. 部署環境差異較大, 也有可能無法連接外網. 所以沒有統一/獨立的部署方式和伺服服務器, 更沒有CDN. 這要求我們的項目是可以獨立部署, 自包含的. 前端項目不能獨立存在和運行, 而是內嵌到後端項目中. 由對應後端項目來管理和伺服靜態資源
方法
前端
發佈版本庫根據前面的版本類型可以劃分為兩種類型的分支
- 開發分支
- master, 直接使用master
- preview和test總是線性迭代的, 對於這個類型的發佈總會推送到開發分支. 後端開發者可以通過這個分支獲取到最新的可交付代碼
- 命名
- 發佈分支
- release/{GZB_version}
- 對於production, 會為每個release版本創建一個分支, 後續該release版本的hotFix都會提交到該分支
- 命名
對於跨項目的情況處理起來相對複雜. 因為各個項目之間版本不是同步的. 解決辦法是:
- 項目之間通過目錄區分和隔離
- 例如gzb-location 會推送到部署目錄下的location目錄
- release分支從最新的開發分支中checkout出來. 這樣可以保證拉取到其他未更新的項目
詳細參考jm-deploy
後端
後端項目使用git submodule的方式關聯前端的發佈版本庫. 這也意味着, 如果發佈版本庫有變動, 後端開發人員需要手動更新submodule到指定提交記錄.
有沒有更好的方式? 還如容易出現錯誤. 可以通過git hook自動更新submodule. 檢查代碼當前分支是否是發佈分支, 確定拉取發佈分支還是開發分支(表示最新版本). 如果未找到對應發佈分支, 則回退拉取開發分支
好處
- 使用git版本庫的方式可以記錄發佈記錄
- 方便後端本地開發, 直接可以通過git工具拉取前端代碼
- 方便人工干預
其他參考方案
- 使用npm管理前端發佈 + HTTP下載
- 本地文件系統維護
模板
gitlab-ci通過定義在根目錄下的gitlab-ci.yml
進行定義, 詳見gitlab文檔
before_script: - echo "[GZB front-end CI]" - nvm install 10 - npm i -g yarn - yarn cache: key: 'ALWAYS' paths: - node_modules/ - dist/ stages: - test - build - deploy .common: &common tags: - node .release_ref: &release_ref - /^release/.*$/ # release 分支 - /^vd+.d+.d+.*$/ # release tag # 單元測試 test: <<: *common stage: test script: echo "No tests yet" # 避免被觸發兩次 except: - /^vd+.d+.d+.*$/ # release tag # 構建 build: <<: *common stage: build script: yarn build --cache-by-npm-version only: *release_ref artifacts: paths: - dist/ expire_in: 1 week # 部署前端資源 deploy: <<: *common stage: deploy script: yarn deploy only: *release_ref
來都來了,走啥走,留個言唄~
IT大咖說 | 關於版權
由「IT大咖說(ID:itdakashuo)」原創的文章,轉載時請註明作者、出處及微信公眾號。投稿、約稿、轉載請加微信:ITDKS10(備註:投稿),茉莉小姐姐會及時與您聯繫!