Conventional Commits(従来のコミット規約)
Conventional Commits v1.0.0仕様に従ってコミットメッセージを作成し、構造化されたコミット履歴、自動CHANGELOG生成、セマンティックバージョニングを実現します。
このスキルを使用するタイミング
このスキルは以下の場合に使用します:
- 構造化されたプロジェクトでgitコミットメッセージを作成する場合
- コミットメッセージの形式をConventional Commits仕様に照らして検証する場合
- コミットメッセージ検証にcommitlintを設定する場合
- コミット履歴からCHANGELOG生成を構成する場合
- セマンティックバージョニングの自動化を実装する場合
- コミットメッセージが仕様に準拠しているかレビューする場合
- チームにコミットメッセージの標準をトレーニングする場合
- semantic-release、commitizen、git-cliffなどのツールと統合する場合
メッセージ構造
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
構成要素
| 構成要素 | 必須 | 説明 | 例 |
|---|---|---|---|
| type | はい | コミットのカテゴリ | feat, fix, docs |
| scope | いいえ | 影響を受けるコードベースの範囲 | (auth), (parser) |
| description | はい | 変更内容の短い要約 | add user authentication |
| body | いいえ | 詳細な説明 | コンテキストを含む複数段落 |
| footer | いいえ | 破壊的変更、Issue参照 | BREAKING CHANGE:, Refs: #123 |
コミットタイプ
必須タイプ(SemVerへの影響)
これらのタイプはConventional Commits仕様で必須であり、セマンティックバージョニングに直接影響します:
flowchart LR
Fix[fix: バグ修正<br/>ユーザー向け] --> PatchVer[PATCH<br/>0.0.X]
Feat[feat: 新機能<br/>ユーザー向け] --> MinorVer[MINOR<br/>0.X.0]
Breaking[BREAKING CHANGE または !<br/>を含む任意のタイプ] --> MajorVer[MAJOR<br/>X.0.0]
style PatchVer fill:#e1f5ff
style MinorVer fill:#fff4e1
style MajorVer fill:#ffe1e1
| タイプ | 説明 | SemVer | 例 |
|---|---|---|---|
feat | ユーザー向けの新機能 | MINOR (0.X.0) | feat: add user authentication |
fix | ユーザー向けのバグ修正 | PATCH (0.0.X) | fix: prevent crash on empty input |
推奨タイプ(Angular規約)
これらのタイプは@commitlint/config-conventional(Angularコミットガイドラインに基づく)に由来します。BREAKING CHANGEを含まない限り、暗黙のSemVer効果はありません。
| タイプ | 説明 | 例 |
|---|---|---|
build | ビルドシステムまたは外部依存関係の変更 | build: update webpack to v5 |
ci | CI設定の変更 | ci: add Node 18 to test matrix |
docs | ドキュメントのみの変更 | docs: update API reference |
perf | パフォーマンスの改善 | perf: reduce bundle size by 20% |
refactor | バグ修正や機能追加を伴わないコード変更 | refactor: extract validation logic |
style | コードスタイルの変更(空白、書式) | style: fix indentation |
test | テストの追加または修正 | test: add unit tests for parser |
その他の一般的なタイプ
| タイプ | 説明 | 例 |
|---|---|---|
chore | srcファイルやテストファイルを変更しない作業 | chore: update .gitignore |
revert | 以前のコミットを取り消す | revert: feat: add user auth |
注記: チームはfeatとfix以外にカスタムタイプを定義できますが、Angular規約のタイプはツールで広くサポートされています。
仕様ルール
以下のルールは、RFC 2119に従ったConventional Commits 1.0.0仕様を構成します。
タイプとスコープ
-
コミットの先頭にはタイプ(
feat、fixなどの名詞)を付けなければなりませんMUST。その後に任意のスコープ、任意の!、そして必須のコロンとスペースを続けます。 -
タイプ
featは、コミットが新機能を追加する場合に使用しなければなりませんMUST。 -
タイプ
fixは、コミットがバグ修正である場合に使用しなければなりませんMUST。 -
スコープはタイプの後に指定してもよいMAY。スコープは、コードベースのセクションを説明する名詞で構成し、丸括弧で囲まなければなりませんMUST。例:
fix(parser): -
descriptionは、タイプ/スコープ接頭辞の後のコロンとスペースの直後に続けなければなりませんMUST。descriptionはコード変更の短い要約です。例:
fix: array parsing issue when multiple spaces were contained in string
本文(Body)
-
短い説明の後に、より詳細なコンテキスト情報を提供する長いコミット本文を記述してもよいMAY。本文は、descriptionの後に1行の空行を挟んで開始しなければなりませんMUST。
-
コミット本文は自由形式であり、改行で区切られた任意の数の段落で構成してもよいMAY。
フッター(Footer)
-
本文の後に1行の空行を挟んで、1つ以上のフッターを記述してもよいMAY。各フッターは、単語トークン、続けて
:<space>または<space>#のセパレータ、続けて文字列値で構成しなければなりませんMUST(git trailer規約に基づく)。 -
フッターのトークンは、空白文字の代わりに
-を使用しなければなりませんMUST。例:Acked-by(これによりフッターセクションを複数段落の本文と区別できます)。例外:BREAKING CHANGEはトークンとして使用してもよいMAY。 -
フッターの値にはスペースや改行を含めてもよいMAY。次の有効なフッタートークン/セパレータペアが観測された時点でパースは終了しなければなりませんMUST。
破壊的変更(Breaking Changes)
-
破壊的変更は、コミットのタイプ/スコープ接頭辞、またはフッターのエントリとして示さなければなりませんMUST。
-
フッターとして含める場合、破壊的変更は大文字のテキスト
BREAKING CHANGEで構成し、コロン、スペース、説明を続けなければなりませんMUST。例:BREAKING CHANGE: environment variables now take precedence over config files -
タイプ/スコープ接頭辞に含める場合、破壊的変更は
:の直前に!を置いて示さなければなりませんMUST。!が使用された場合、BREAKING CHANGE:をフッターから省略してもよくMAY、コミットのdescriptionを破壊的変更の説明として使用しますSHALL。
追加ルール
-
featとfix以外のタイプはコミットメッセージで使用してもよいMAY。例:docs: update ref docs -
Conventional Commitsを構成する情報の単位は、実装者によって大文字小文字を区別して扱ってはなりませんMUST NOT。ただし、
BREAKING CHANGEは大文字でなければなりませんMUST。 -
BREAKING-CHANGEは、フッターのトークンとして使用される場合、BREAKING CHANGEと同義でなければなりませんMUST。
Descriptionのベストプラクティス
Angularコミットメッセージガイドラインに基づきます:
サマリー/Descriptionのガイドライン
- 命令形、現在形を使用:「changed」ではなく「change」、「changes」ではなく「change」
- 最初の文字を大文字にしない
- 末尾にピリオド(.)を付けない
- ヘッダー全体(タイプ + スコープ + description)を72文字以内に収める
良い例
feat: add validation for email input
fix: handle null pointer in user service
docs: update installation instructions
refactor: simplify authentication flow
悪い例(避けるべき)
feat: Added validation for email input # 過去形
fix: Handles null pointer in user service # 三人称
docs: Update installation instructions. # 末尾にピリオド、大文字
FEAT: add validation # タイプが大文字(一貫性がない)
本文のガイドライン
- 命令形、現在形を使用(サマリーと同じ)
- 変更の動機を説明する
- 可能であれば、以前の動作と新しい動作の比較を含める
- 本文はdescriptionの後に1行の空行から開始しなければなりませんMUST
- 本文がある場合の推奨最低文字数: 20文字
破壊的変更(Breaking Changes)
破壊的変更を示す方法
3つの同等なアプローチ:
-
フッター表記:
feat: allow provided config object to extend other configs BREAKING CHANGE: `extends` key in config file is now used for extending other config files -
タイプに
!を付加:feat!: remove support for Node 6 -
タイプ+スコープに
!を付加:feat(api)!: send an email to the customer when a product is shipped
ルール
BREAKING CHANGEは大文字でなければなりませんMUSTBREAKING-CHANGEはフッタートークンとして使用される場合、同義です- 破壊的変更はSemVerのMAJORバージョンアップと関連付けなければなりませんMUST
セマンティックバージョニングとの関連
flowchart TD
Start([コミットを分析]) --> CheckBreaking{いずれかのコミットに<br/>BREAKING CHANGE<br/>または ! がある?}
CheckBreaking -->|はい| Major[MAJOR バンプ<br/>X.0.0]
CheckBreaking -->|いいえ| CheckFeat{いずれかのコミット<br/>が feat か?}
CheckFeat -->|はい| Minor[MINOR バンプ<br/>0.X.0]
CheckFeat -->|いいえ| CheckFix{いずれかのコミット<br/>が fix か?}
CheckFix -->|はい| Patch[PATCH バンプ<br/>0.0.X]
CheckFix -->|いいえ| NoChange[バージョン変更なし]
Major --> End([リリース])
Minor --> End
Patch --> End
NoChange --> End
コミットタイプとバージョンの対応
| コミットタイプ | バージョンバンプ |
|---|---|
fix | PATCH (0.0.X) |
feat | MINOR (0.X.0) |
BREAKING CHANGE または ! | MAJOR (X.0.0) |
理由: コミット履歴に基づく自動セマンティックバージョニングを可能にします。
検証パターン
ヘッダー検証の正規表現
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?:\s.+$
Python 検証例
import re
CONVENTIONAL_COMMIT_PATTERN = re.compile(
r"^(?P<type>feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)"
r"(?:\((?P<scope>[^)]+)\))?"
r"(?P<breaking>!)?"
r":\s"
r"(?P<description>.+)$"
)
def validate_header(header: str) -> bool:
"""コミットヘッダーがConventional Commitsに従っているか検証"""
return bool(CONVENTIONAL_COMMIT_PATTERN.match(header))
def parse_header(header: str) -> dict | None:
"""コミットヘッダーを構成要素にパース"""
match = CONVENTIONAL_COMMIT_PATTERN.match(header)
if not match:
return None
return {
"type": match.group("type"),
"scope": match.group("scope"),
"breaking": bool(match.group("breaking")),
"description": match.group("description"),
}
完全な例
シンプルなコミット
feat: add user authentication
fix: prevent crash on empty input
docs: correct spelling of CHANGELOG
スコープ付きコミット
feat(lang): add Polish language
feat(parser): add ability to parse arrays
fix(auth): handle token expiration correctly
破壊的変更
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
feat!: send an email to the customer when a product is shipped
feat(api)!: send an email to the customer when a product is shipped
chore!: drop support for Node 6
BREAKING CHANGE: use JavaScript features not available in Node 6.
複数段落の本文とフッター
fix: prevent racing of requests
Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.
Remove timeouts which were used to mitigate the racing issue but are
obsolete now.
Reviewed-by: Z
Refs: #123
取り消しコミット
revert: let us never again speak of the noodle incident
Refs: 676104e, a215868
パフォーマンス改善
perf: reduce memory allocation in parser by 40%
Replace string concatenation with StringBuilder pattern.
Benchmark results show 40% reduction in heap allocations.
Refs: #456
リファクタリング
refactor: extract authentication logic into separate module
Move auth-related functions from utils.py to auth.py.
No functional changes.
ビルド/CIの変更
ci: add Node 18 to test matrix
build: upgrade webpack from v4 to v5
- Update webpack.config.js for v5 compatibility
- Replace deprecated plugins
- Update all loader dependencies
Refs: #789
テストとスタイルの変更
test: add unit tests for user validation
Cover edge cases for email validation and password strength.
style: format code according to prettier config
chore: update .gitignore to exclude IDE files
検証ツールとの統合
commitlintの設定
Angular設定を使用してcommitlintでコミットを検証:
# commitlintのインストール
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# 設定の作成
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
# コミットメッセージのテスト
echo 'feat(api): add new endpoint' | npx commitlint
包括的なcommitlint設定ガイダンスについては、このドキュメントの指示に従ってください。ワークスペースにインストールされたcommitlintプラグインがある場合は、プロジェクト固有のルールと例についてはそれを優先してください。
プリコミットフック
プリコミットフックでコミットメッセージ形式を強制します。ワークスペースにインストールされたプリコミットプラグインがある場合は、フック設定のガイダンスにそれを使用してください。それ以外の場合は、フックを直接設定してください。
CHANGELOG生成
semantic-releaseを使用してConventional CommitsからCHANGELOGを生成:
// release.config.js
module.exports = {
branches: ['main'],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/changelog',
'@semantic-release/github',
'@semantic-release/git',
],
};
huskyとcommitlintの統合
huskyを使用してコミット時にコミットメッセージの検証を強制:
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
git-cliffの設定
# cliff.toml
[changelog]
header = "# 変更履歴"
body = """
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }}
{% endfor %}
{% endfor %}
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = true
CI/CDパイプラインでのワークフロー
GitHub Actionsの設定例
GitHub Actionsでsemantic-releaseを設定:
name: リリース
on:
push:
branches:
- main
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GitLab CIの設定例
# .gitlab-ci.yml
stages:
- validate
- release
commitlint:
stage: validate
script:
- npm install @commitlint/cli @commitlint/config-conventional
- npx commitlint --from $CI_MERGE_REQUEST_DIFF_BASE_SHA --to $CI_MERGE_REQUEST_DIFF_HEAD_SHA
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
semantic_release:
stage: release
script:
- npm install semantic-release
- npx semantic-release
rules:
- if: $CI_COMMIT_BRANCH == 'main' && $CI_PIPELINE_SOURCE == 'push'
手動CHANGELOG検証
# gitログからCHANGELOGの概要を生成
git log --oneline --decorate --no-merges v1.0.0..HEAD | while read line; do
if echo "$line" | grep -qE '^(feat|fix|docs|chore|refactor|perf|test|build|ci|style|revert)'; then
echo "$line"
fi
done