Angular 工具篇之規範化Git版本管理
- 2019 年 11 月 5 日
- 筆記
目前很多的項目都已經使用 Git 作為版本控制工具,使用 Git 意味著我們每天都要與 Git Commit Message 打交道。Git Commit Message 看似簡單,但實際卻很重要。通過 Git Commit Message 我們可以快速地了解本次提交的資訊,比如解決了哪個 Bug、優化了什麼問題或新增了什麼功能等。
俗話說得好,無規矩不成方圓。因為 Git Commit Message 很重要,所以為了能夠更好地進行項目開發與維護,我們就需要規範化 Git Commit Message,除此之外,規範化 Git Commit Message 還有以下的好處,比如:
- 自動化生成 CHANGELOG。
- 基於提交的類型,自動決定語義化的版本變更。
- 向同事、公眾與其他利益關係人傳達變化的性質。
- 觸發構建和部署流程。
- 讓人們更容易地探索結構化的提交歷史,降低貢獻項目的難度。
那麼應該如何規範化 Git Commit Message,這裡我們可以使用開源社區為我們總結出了一套名為 Conventional Commits 的書寫規範,該規範受到了 Angular Commit Guidelines 的啟發,並在很大程度上以其為依據。它規定的格式如下:
<type>[optional scope]: <description> [optional body] [optional footer]
type 用於表示此次改動的類型,目前常用的主要有以下幾種:
- feat 新功能(feature)表示在程式碼庫中新增了一個功能(這和語義化版本中的
MINOR
相對應) - fix 表示在程式碼庫中修復了一個 bug(這和語義化版本中的
PATCH
相對應) - docs 文檔(documentation)
- style (格式化, 缺失分號等; 不包括生產程式碼變動)
- refactor (重構程式碼)
- perf (性能優化)
- test (添加缺失的測試, 重構測試, 不包括生產程式碼變動)
- chore (更新grunt任務等; 不包括生產程式碼變動)
scope:一個可選的修改範圍,用於標識此次提交主要涉及到程式碼中哪個模組。
description:簡明扼要描述本次提交的內容,首字母無需大寫,結尾不需要使用 .
。
optional body:詳細描述本次提交,比如此次變更的動機,如需換行,則使用 |
。
optional footer:描述與之關聯的 issue 或 break change。
Conventional Commits 示例
- 包含了描述與正文內破壞性變更的提交說明
feat: allow provided config object to extend other configs BREAKING CHANGE: `extends` key in config file is now used for extending other config files
- 不包含正文的提交說明
docs: correct spelling of CHANGELOG
- 包含作用域的提交說明
feat(lang): added polish language
- 為 fix 編寫的提交說明,包含可選的 issue 編號
fix: minor typos in code see the issue for details on the typos fixed fixes issue #12
現在 Git Commit Message 規範已經找到了,但僅僅靠規範還是不能保證項目中的每個成員都遵循規範。這時我們還需要一個工具,能夠智慧地檢測我們的 commit message 是否符合規範的要求。值得慶幸的是,現在已經有現成的工具了,它就是 commitlint,接下來我們來介紹在項目中如何使用 commitlint。
commitlint 項目實戰
首先我們要先安裝 commitlint 以及 conventional 規範:
# Install commitlint cli and angular config $ npm install --save-dev @commitlint/{config-conventional,cli} # For Windows: $ npm install --save-dev @commitlint/config-conventional @commitlint/cli
接著在命令行輸入以下命令:
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
運行以上命令後項目會生成 commitlint.config.js。當然我們也可以手動創建 commitlint.config.js 文件,然後在文件內輸入以下內容:
module.exports = {extends: ['@commitlint/config-conventional']}
現在我們已經完成了 commitlint 的配置,但我們還需要在每次提交時,自動觸發 commitlint 進行規範檢查。要實現這個功能,我們可以藉助另一個工具 husky。
? Git hooks made easy Husky can prevent bad
git commit
,git push
and more ? woof!
husky 是一個增強的 git hooks 工具,它讓我們可以在 git hook 的各個階段運行 package.json 中設定的任務。
下面我們繼續來安裝 husky:
$ npm install --save-dev husky
安裝完成後,我們需要在 package.json 文件中添加以下的配置項:
"husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } }
完成上述的配置後,我們可以驗證一下 commitlint 是否生效:
- 不符合規範的 commit message
$ git commit -m "foo: this will fail"
以上命令運行後,會輸出以下資訊:
husky > commit-msg (node v9.11.0) ⧗ input: foo: this will fail ✖ type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test] [type-enum] ✖ found 1 problems, 0 warnings husky > commit-msg hook failed (add --no-verify to bypass)
- 符合規範的 commit message
$ git commit -m "chore: lint on commitmsg"
以上命令運行後,會輸出以下資訊:
usky > commit-msg (node v9.11.0) ⧗ input: chore: lint on commitmsg ✔ found 0 problems, 0 warnings [master 394dce6] chore: lint on commitmsg
如果我們項目的 Git Commit Message 嚴格遵守 conventional 規範,那麼在發布版本時,我們就可以自動生成 CHANGELOG,這裡我們可以使用的是 standard-version 這款工具。
? Replacement for
npm version
with automatic CHANGELOG generation
顧名思義,standard-version 用於替代 npm version
,同時還能自動生成 CHANGELOG。最後,我們來簡單介紹一下 standard-version 這款工具。
standard-version 簡介
在介紹 standard-version 之前,我們先來簡單了解一下 Semver(Semantic Versioning) 規範,該規範規定了版本號如何表示,如何增加,如何進行比較,不同的版本號意味著什麼。
版本格式:主版本號.次版本號.修訂號,版本號遞增規則如下:
- 主版本號(major):當你做了不兼容的 API 修改。
- 次版本號(minor):當你做了向下兼容的功能性新增,可以理解為 Feature 版本。
- 修訂號(patch):當你做了向下兼容的問題修正,可以理解為 Bug fix 版本。
先行版本號及版本編譯資訊可以加到 「主版本號.次版本號.修訂號」 的後面,作為延伸。Semver 規範中使用alpha、beta、rc 來修飾即將要發布的版本。它們的含義是:
- alpha:內部版本。
- beta:公測版本。
- rc:即 Release Candiate,正式版本的候選版本。
在發布 npm 包時,為了讓我們更好的遵從 Semver 規範,npm 為我們提供了 npm version 命令,具體使用方式如下:
- 升級修補程式版本號:npm version patch。
- 升級小版本號:npm version minor。
- 升級大版本號:npm version major。
關於 Semver(語義化版本號) 的相關內容,這裡我們不再詳細展開。感興趣的同學,可以閱讀 騰訊IVWEB團隊 發布的 Semver(語義化版本號)掃盲 這篇文章。接下來我們開始介紹 standard-version 這款工具。
首先以 local 模式安裝 standard-version:
$ npm install --save-dev standard-version
然後在 package.json 的 scripts 中添加以下配置:
{ "scripts": { "release": "standard-version" } }
若需要發布首個版本,則可以運行以下命令:
$ npm run release -- --first-release
如果需要發布預發布版本,則可以使用 --prerelease
標誌,比如:
$ npm run release -- --prerelease
假設你當前最新的版本是 v1.0.0
,在運行上述命令後,你的版本將變為 v1.0.1-0
。此外,如果你的預發布版本要包含 alpha
前綴,你可以通過 --prerelease <name>
設定前綴:
$ npm run release -- --prerelease alpha
此時,當前版本將變為 1.0.1-alpha.0
。除了 --first-release
和 --prerelease
標識外,standard-version 還支援一個很有用的標誌 --release-as
,它支援三種不同的參數: major
, minor
或 patch
,使用方式如下:
$ npm run release -- --release-as minor
為了方便地進行版本發布,我們也可以在 npm scripts 中定義對應的任務,比如:
{ "release:minor": "standard-version --release-as minor && git push --follow-tags origin master", "release:major": "standard-version --release-as major && git push --follow-tags origin master" }