cover

上篇裝好了 CommitLint + Husky,這篇講怎麼把整個 commit 工作流武裝到牙齒。沒看過上篇的先去:CommitLint:讓你的 Git 提交訊息不再像亂碼

先講結論

CommitLint 不是一個人在戰鬥。完整的 commit 工作流長這樣:

  1. lint-staged:commit 前只對你改的檔案跑 lint / format
  2. commitizen:互動式 CLI,選一選就能組出合規的 commit message
  3. standard-version:根據 commit 類型自動決定版號、產生 CHANGELOG

全部裝完,你的 commit 流程是:改 code → git addnpx cz → lint-staged 自動格式化 → CommitLint 檢查訊息 → commit 成功。

lint-staged:不要每次都掃全部

你的專案有上千個檔案,每次 commit 都對整個 codebase 跑 ESLint + Prettier?等到天荒地老。lint-staged 只對 staged files 執行檢查,速度差十倍不誇張。

npm install --save-dev lint-staged
echo 'npx lint-staged' > .husky/pre-commit

package.json 加設定:

{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{css,scss,json,md}": ["prettier --write"]
  }
}

這樣 commit 時會先跑 pre-commit(lint-staged),再跑 commit-msg(CommitLint)——兩道關卡,程式碼品質和訊息品質都顧到。

commitizen:記不住格式?用選的

團隊剛導入 CommitLint 的前幾天,一定有人不斷被擋:「feat 後面要加冒號嗎?」「scope 要不要加括號?」commitizen 直接給你選單:

npm install -g commitizen
commitizen init cz-conventional-changelog --save-dev --save-exact

之後用 npx cz 取代 git commit

? Select the type of change:
❯ feat:     A new feature
  fix:      A bug fix
  docs:     Documentation only changes
  ...

? Scope: login
? Short description: add user authentication

自動幫你組出 feat(login): add user authentication。填空題變選擇題,終於不用再被 CommitLint 羞辱了

standard-version:自動版號 + CHANGELOG

當所有 commit 都遵循 Conventional Commits,工具就能自動做版本管理:

npm install --save-dev standard-version
npx standard-version

它會幫你:

  • feat → minor 版號升級(1.1.0 → 1.2.0)
  • fix → patch 版號升級(1.2.0 → 1.2.1)
  • 自動更新 package.json 的 version
  • 產生 CHANGELOG.md
  • 建一個 tag commit

產出的 CHANGELOG 長這樣:

## [1.2.0] (2024-09-15)
 
### Features
* **login:** add user authentication (a1b2c3d)
 
### Bug Fixes
* **api:** fix token refresh issue (i7j8k9l)

standard-version 已進入維護模式,新專案可以考慮 release-please。但對中小型專案,standard-version 依然夠用。

完整 package.json 長怎樣

把上面的工具全部裝完,你的 package.json 大概是這樣:

{
  "scripts": {
    "prepare": "husky",
    "release": "standard-version",
    "commit": "cz"
  },
  "devDependencies": {
    "@commitlint/cli": "^19.0.0",
    "@commitlint/config-conventional": "^19.0.0",
    "cz-conventional-changelog": "^3.3.0",
    "husky": "^9.0.0",
    "lint-staged": "^15.0.0",
    "standard-version": "^9.5.0"
  },
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{css,scss,json,md}": ["prettier --write"]
  },
  "config": {
    "commitizen": { "path": "./node_modules/cz-conventional-changelog" }
  }
}

搭配 .husky/ 裡的兩個 hook:

# .husky/pre-commit
npx lint-staged
 
# .husky/commit-msg
npx --no -- commitlint --edit "$1"

團隊導入:拜託不要一次全上

一次把四個工具砸到團隊臉上,保證被翻桌。我的建議是分四階段,每階段隔一到兩週:

第一週:CommitLint + Husky 最小可行方案。只要求 commit message 格式,不動程式碼。附一份小抄列出常用 type 就好。

第二~三週:加 lint-staged 團隊習慣新格式後,加上自動格式化。這一步幾乎無痛,因為它是自動修的。

第三~四週:加 commitizen 如果還是有人一直被擋,就給他選單工具。通常這時候大部分人已經不需要了。

有版本發佈需求時:加 standard-version 等 commit history 穩定了,再加自動版號管理。這個不急,但加了會很爽。

導入工具的目的是幫團隊,不是給團隊添堵。急著一次到位,只會讓大家把你的 PR 標成 wontfix


工具是死的,流程是活的。最好的工具鏈,是團隊願意用的那一套。

參考資源