如何構建基於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版本號作為』功能』
  • 合併時機
    1. 當feature分支迭代穩定, 並通過測試後, 合併到dev分支. 合併到dev後, feature分支的生命周期就結束了. 後續bug修復和功能優化直接在dev開發
    2. 當多個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就得重新打
    1. 進行代碼變更
    2. 提交這些變更, 進行CI讓這些變更通過測試
    3. 提升package.json的版本號, 更新CHANGELOG.md
    4. 打上tag, 提交
    5. 可選. 合併到release分支
  • 工具
    • 使用jm-deploy release自動化發佈並生成CHANGELOG.md

持續集成

前端項目基於公司內部部署的gitlab-ci來進行持續部署。包含以下階段(stage):

持續集成階段

  • 檢查:包括單元測試和代碼lint。
    • 所有push到版本庫的代碼都會跑這個階段. 可以在提交title中包含[ci skip]來跳過這個階段
  • 構建: 對前端項目進行構建.
    • 只有打上版本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(備註:投稿),茉莉小姐姐會及時與您聯繫!

Exit mobile version