Why

當我們瀏覽一個項目的 commit 歷史時,經常發現它們可讀性很差,不知所云,不明白它們解決了什麼問題或者增加了什麼新特性。 就算可以通過 diff 工具知道那些文件變更了,如果 commit message 寫得很糟糕,語義不清,很難知道為什麼要做這些變更。

比如下面來自本人某個真實項目的糟糕例子:

bad commits

上圖很多提交只是簡單地描述做了哪些變更,新建或者刪除了某些文件。而且像add width: 100%, fix flow error 這些信息,依然讓人很困惑,是修改了某個公共模塊還是某個特定模塊或頁面,會不會有意外的影響?

message是對commit的總結、注釋,不是簡單地描述做了什麼變更(CRUD某個文件),更應該是讓閱讀歷史的人明白,你為什麼做了這些變更,這些變更影響了哪些模塊或頁面,是否修復了某些 bug,是否是break change,儘可能讓項目的其他成員理解此次commit的上下文、意圖。

好的commit message,可以提高code review的速度,方便歷史回溯,還可以幫助自動生成更新日誌。

Convention

很多開源項目會在CONTRIBUTING中說明它們採用的commit message格式,大同小異,以目前javascript社區比較出名的、最先由Angular團隊推出的conventional-changelog舉例。

首先,格式是:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

再看一個具體的例子:

type scope subject
| | |
| | |
| | |
feat(button): add disabled prop ---- subject line
---- blank
prevent to click when button is disabled ---- body, long description
---- blank
Fixes #bugID ---- footer, issue/bug reference
---- blank
BREAKING CHANGE: just to illustrate ---- footer, Beeaking change

在詳細講解每個值的意思之前,有幾點需要共識:

  1. subject linebodyfooter 互相必須以空行隔開。因為bodyfooter可以是多行的。
  2. subject限制為 50 個字元
  3. subject不以.結尾

type

必須是以下值的一個。參考Angular 項目的 Contribution.md,裡面已經解釋得很清楚。

  • build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)。依賴項的變更需要單獨提交。如果添加某個依賴 A,那可能是`build(npm): add dependenceA

  • ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) 比如對文件格式化
  • test: Adding missing tests or correcting existing tests

清晰地分類,提倡大家使用意圖明確、單一目標的小提交,而不是混雜的大提交。

Scope

可選,表示影響的範圍、功能、模塊

Subject

對變更的簡潔描述

Body

更詳細的描述

Footer(Metadata)

  • 如果修復了某個缺陷,可以添加對其的引用,如Fixes #xx
  • 如果是Breaking change,在此註明。

Tools

commitlint

首先,我們需要commitlint來檢查我們的commit message是否符合規範。如果不符合,它會攔截提交並給出理由。

這點是通過git hooks來實現的

// package.json

"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
}
}

還有,我們需要配置告訴commitlint項目採用的標準,其實就是配置一些規則,有點像eslint。比如

# .commitlintrc.yml

extends:
- "@commitlint/config-conventional"
rules:
subject-case: # 中文需要忽略該選項
- 0

詳細的安裝、配置步驟在裏就不展開。

commitizen

對於初次接觸的開發員而言,完全手寫符合規範的message可能有點不適應,這時候可以藉助 commitizen

commitizen提供可交互命令行界面,開發者通過回答問題來生成最終的commit message

cz-cli

同樣,我們需要告訴commitizen項目採用的標準:

// package.json

"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},

Advanced

有了這些附帶上下文、metadata的歷史後,我們可以藉助conventional-changelog 自動生成對應的變更日誌

conventional-changelog -p angular -i CHANGELOG.md -s -r 0

-p angular表示使用Angular規範。

生成的CHANGELOG.md大概長這樣:

Karma 的部分 changelog

Customize

可以看到,如果我們想要充分自定義我們自己的規範,藉助上述的工具,我們只需要

  1. 自定義的commitlint規則
  2. 自定義的commitizen配置,提交的時候回答我們自定義的問題。
  3. 自定義的conventional-changelog配置,根據message裡面的數據,按照我們自定義的魔板生成 changelog

推薦閱讀:

相關文章