Skip to main content

約定式提交 (Conventional Commits)

Conventional Commits 是一種 commit message 的規範, 透過統一的格式來描述 commit 的內容, 並且可以透過 commit message 來自動生成 changelog, 並且可以透過 commit message 來自動判斷版本號​

參考 https://www.conventionalcommits.org 來給予 commit 的訊息更多語義的格式規範

常見類型​

  • feat: 表示新增了一個新功能或者在項目中加入或修改了顯著的新內容

  • fix: 用於修復 bug

  • docs: 僅僅更改了文件, 用於沒有改動程式碼的文件更新

  • style: 不影響程式碼含義的更改 (空格, 格式化, 缺少分號, coding style...etc.)

  • refactor: 重構現有的程式碼, 既不修正 bug 也不添加功能, 通常指修改程式碼以提高可讀性, 簡化結構或改善性能, ex:

    • remove unused code
  • perf: 用於提高程式效能的更改

  • test: 新增或修改測試

  • build: 影響 build or deps 的更改 (ex: npm, gulp)

  • ci: 與 ci/cd 相關的配置文件或 scripts (ex: GitHub actions workflow)

  • chore: 其他不修改 src 或 test 文件的更改, ex:

    • storybook, eslint, prettier, husky, lint-staged...etc.
    • console.log, debugger
    • 版號更新: chore(release): v1.0.0
    • console.log (或自定義 type)
  • revert: 用於撤銷之前的 commit

  • 也可以自訂特定於團隊自己約定的類型, ex: debug (如果團隊有這樣的約定), 可以用來開發中臨時需要增加 log 做測試的情況

影響範圍​

影響範圍可以是可以是元件、檔名或或特定的功能, 以 monorepo 來說也可以針對各別 project 來做區分, 區分方式是用括號包起來, 例如:

  • feat(client): add login button
  • fix(server): fix require lodash not defined
  • feat(client/login): add login page
  • fix(client/SomeFeature): fix SomeFeature return error

BREAKING CHANGE​

用於重大變更, 或可能會破壞現有程式碼的變更, 通常會在描述中加入 BREAKING CHANGE: 來描述變更的內容, 通常有兩種方式:

  1. 在 commit msg 底部:

    feat: allow provided config object to extend other configs

    BREAKING CHANGE: `extends` key in config file is now used for extending other config files
  2. 在類型加上 ! 來表示重大變更

    feat!: allow provided config object to extend other configs

關聯 issue​

可以在 commit msg 中加入關聯的 issue/ticket, ex:

  • feat: add login page #123

Commitizen​

Commitizen 是一個幫助我們撰寫符合約定式提交規範的 commit message 的工具, 透過命令列的方式來引導我們撰寫 commit message, 並且可以透過 git cz 來取代 git commit 來使用

安裝 Commitizen​

pnpm add commitizen -D

將 Commitizen 的指令 cz 加入 package.json 的 scripts 中

{
"scripts": {
"commit": "git cz"
}
}

或者使用 cz-conventional-changelog adapter 來執行 Commitizen:

pnpm add cz-conventional-changelog -D

並且在 package.json 中加入以下設定:

{
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
}

執行 scripts 後就可以在 cmd 中透過 Commitizen 的方式來撰寫 commit message, 全部回答完後會產生一個符合約定式提交規範的 commit message, 並且會自動 commit

Commitlint​

Commitlint 是一個用來檢查 commit message 是否符合約定式提交規範的工具, 透過使用正規表達式來檢查 commit message 是否符合規範, 並且可以透過 git hooks 來在 commit 時檢查 commit message

Husky​

Husky 是一個用來設定 git hooks 的工具, 可以透過 husky 來設定 pre-commit hook 在 commit 時檢查 commit message 是否符合約定式提交規範, 或者在提交前執行 lint, test 等操作

Commitizen + Commitlint + Husky 結合一起使用​

安裝​

pnpm add husky commitizen @commitlint/cli @commitlint/config-conventional -D

搭配 @commitlint/cz-commitlint 使用​

pnpm add @commitlint/cz-commitlint -D

並且在 package.json 中加入以下設定:

{
"config": {
"commitizen": {
"path": "@commitlint/cz-commitlint"
}
}
}
  1. 初始化 husky 產生 .husky:

    pnpm exec husky init
  2. 新增 commitlint.config.js 來配置 commitlint 設定:

    module.exports = { extends: ['@commitlint/config-conventional'] };
  3. 設置 husky prepare-commit-msg hook:

    #!/usr/bin/env sh

    if [ -t 0 ]; then
    # 如果在終端中運行
    exec < /dev/tty && [ -z "$(cat "$1")" ] && pnpm exec cz --hook || true
    else
    # 如果在 GUI 中運行
    [ -z "$(cat "$1")" ] && pnpm exec cz --hook || true
    fi

    用於在 Git 提交過程中自動觸發 Commitizen cmd, 以便生成符合特定格式的 commit msg

  4. 設置 husky pre-commit hook 並搭配 eslint-staged:

    pre-commit hook:

    #!/usr/bin/env sh

    # lint-staged
    echo "Running lint-staged..."
    pnpm exec lint-staged

    # if lint-staged fails, don't commit
    if [ $? != 0 ]; then
    echo "Linting failed, commit aborted"
    exit 1
    fi

    lint-staged:

    pnpm add lint-staged -D

    package.json:

    {
    "lint-staged": {
    "apps/cas-server/*.{js,jsx,ts,tsx}": ["turbo run lint --filter cas-server --"],
    "apps/vite-demo/*.{js,jsx,ts,tsx}": ["turbo run lint --filter vite-demo --", "turbo run lint:css --filter vite-demo --"],
    "apps/**/*.{js,jsx,ts,tsx}": ["pnpm run format"],
    "apps/**/*.{css,scss}": ["pnpm run format", "turbo run lint:css --"],
    "apps/**/*.{html,md}": ["pnpm run format"]
    }
    }

    因為每個需要檢查的需求及規則會有所不同, 需要針對對應的 repo 去設定 script

    在 Git 提交過程中自動觸發 lint-staged, 以便在提交前先進行 eslint 及 prettier 的檢查, 其中 lint-staged 只檢查 staged 的檔案, 以減少檢查時間

  5. 設置 husky commit-msg hook:

    #!/bin/sh

    pnpm exec commitlint --edit $1

    用於在 Git 提交過程中自動觸發 commitlint, 以便在提交前檢查 commit message 是否符合約定式提交規範

當要使用時執行 pnpm cz 即可在 cmd 上透過 Commitizen 的方式來撰寫 commit message


註1: commitling.config.js 檔案須為 UTF-8 編碼, 否則會報錯

1.png

註2: lint 相關的設定可參考 docs/lint

註3 : 可以再搭配 git-cliff 來自動生成 changelog

  1. 在 root 安裝 git-cliff, init cliff (需要 template 可以參考此, 這邊只用 default)
    pnpm add git-cliff -D
    git cliff --init
  2. 在 package.json 中加入以下設定:
    {
    "scripts": {
    "changelog": "git-cliff -o CHANGELOG.md"
    }
    }
    也可以指定特定 workspace apps
    {
    "scripts": {
    "changelog": "git-cliff --include-path 'packages/config-eslint/**/*' -o CHANGELOG.md"
    }
    }

refs: