自動化

Conventional Commitsとは?書き方・type一覧とSemVer連携を実例で解説

Conventional Commitsとは?書き方・type一覧とSemVer連携を実例で解説

Conventional Commits(コンベンショナル・コミット)は、Gitのコミットメッセージを type(scope): description という決まった形式で書くための規約です。メッセージの先頭に feat(機能追加)や fix(バグ修正)といった種類(type)を付けるだけで、変更の意図が一目で伝わり、リリースノートやバージョン番号の生成を機械が自動化できるようになります。この記事では、読み方・基本の書式・type一覧・SemVerとの対応・commitlintなどでの導入手順、そして導入すべきでない場面までを、コミット例とともに解説します。

まとめ:Conventional Commitsの要点

  • 正式な読み方は「コンベンショナル・コミット」。「カンバセーショナルコミット」は誤読で、意味は「規約に基づいたコミット」。
  • 書式は type(scope): description。1行目のヘッダーが必須で、任意でボディ・フッターを続ける。
  • typeはfeat・fixが中核。仕様(v1.0.0)で意味が定義されるのは feat と fix のみで、docs・style・refactor などは commitlint の慣習セット由来。
  • SemVerと直結。feat→MINOR、fix→PATCH、破壊的変更(! または BREAKING CHANGE:)→MAJOR。
  • 強制はツールで。commitlint+huskyでフォーマット違反を弾き、commitizenで対話式に作成、semantic-releaseでリリースまで自動化できる。
  • 小規模・短期プロジェクトでは形式順守のコストが上回ることもある。全プロジェクトで一律に必須ではない。

Conventional Commitsとは(定義と読み方)

Conventional Commitsは、コミットメッセージの構造を統一するための軽量な規約で、公式仕様は conventionalcommits.org で v1.0.0 として公開されています。「Conventional」は「慣習的な・規約に基づいた」という意味で、正しい読み方はコンベンショナル・コミットです。検索では「カンバセーショナルコミット」という表記も見られますが、これは誤読で、同じものを指しています。

規約が解決するのは「コミットメッセージが人によってバラバラで、履歴から変更の意図が読み取れない」という問題です。先頭に変更の種類(type)を機械可読な形で付けることで、コミット履歴がそのままリリースノートやバージョン判定の入力データになります。人間が読みやすくなるだけでなく、後段の自動化が効くのが最大の狙いです。

コミットメッセージの基本構造(書式・形式)

Conventional Commitsのメッセージは、必須のヘッダーと、任意のボディフッターで構成されます。全体像は次のとおりです。

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

ヘッダー:type(scope): description の3要素

1行目のヘッダーだけが必須です。type は変更の種類、scope(省略可)は変更した範囲、description は変更内容の要約を書きます。

feat(auth): add login with one-time password

typedescription の間はコロンと半角スペースで区切ります。description は現在形・命令形の動詞で始め(「add」「fix」など)、末尾にピリオドは付けないのが慣習です。ヘッダーは50〜72文字程度に収めると git log --oneline やGitHub上で折り返されにくくなります。

ボディとフッター:詳細・Issue番号・破壊的変更

ヘッダーの後に1行空けてボディを書くと、変更の背景や理由といった「なぜ」を補足できます。さらに1行空けたフッターには、関連するIssue番号や破壊的変更を記載します。

fix(api): reject expired session tokens

Sessions older than 24h were still accepted because the
expiry check compared seconds against milliseconds.

Refs: #482

フッターの Refs: #482Closes #482 は、GitHubのIssueと変更を紐付けるために使います。Issueの運用方法はGitHub Issueの使い方・書き方もあわせて参考にしてください。

破壊的変更(BREAKING CHANGE)の書き方

後方互換性を壊す変更は、2通りの方法で明示します。仕様が定めるトリガーで、リリースのMAJORバージョンを上げます。

# 方法1: typeの直後に ! を付ける
feat(api)!: drop support for v1 auth header

# 方法2: フッターに BREAKING CHANGE: を書く
feat(api): switch auth header to bearer token

BREAKING CHANGE: the X-Auth-Token header is no longer read.

!BREAKING CHANGE: はどちらか一方でも、両方併記でも構いません。fix! のように fix と組み合わせても、破壊的変更がある以上は MAJOR 扱いになります。この記法を漏らすと自動化ツールがMAJORアップを検知できないため、破壊的変更のときは必ず入れます。

typeの一覧と使い分け

仕様(v1.0.0)が意味を定義しているtypeは featfix の2つだけです。それ以外の docschore などは、広く使われている @commitlint/config-conventional(Angularの規約が基)が推奨する慣習的なtypeで、AngularやVue.jsなど主要OSSの多くが採用しています。主なtypeとSemVerへの影響は次のとおりです。

type 意味 SemVerへの影響
feat 新機能の追加 MINOR
fix バグ修正 PATCH
docs ドキュメントのみの変更 なし
style 整形・空白など動作に影響しない変更 なし
refactor 機能変更を伴わない内部改善 なし
perf パフォーマンス改善 PATCH相当
test テストの追加・修正 なし
build ビルドシステム・依存関係の変更 なし
ci CI設定・スクリプトの変更 なし
chore 上記以外の雑多な変更 なし
revert 過去のコミットの取り消し 内容による

破壊的変更を含むコミットは、typeが何であっても MAJOR を上げます(表の「影響」は破壊的変更が無い場合の目安です)。

feat・fix・docsなど主要typeの具体例

「feat git」「chore git」などの検索で迷いやすいのは、変更をどのtypeに割り当てるかです。判断は「利用者から見て動作が変わるか」で切り分けると安定します。

feat(cart): allow saving items for later
fix(cart): prevent negative quantity on update
docs(readme): add setup steps for Windows
refactor(cart): extract price calculation into a helper
chore(deps): bump eslint to 9.0.0

新機能なら feat、不具合の是正なら fix、READMEやコメントだけなら docs、依存の更新やビルド周りは chorebuild を使います。動作に影響しない整形だけの変更は style に分類し、fix と切り分けます。

scopeの付け方と省略の判断

scope は変更の影響範囲を丸括弧で示す任意項目です。feat(auth) のようにモジュール名・機能名を入れると、履歴を範囲で絞り込めます。scope名はチームで一覧化して固定するのがおすすめで、プロジェクト横断で対象が定まらない変更は省略して feat: ... と書けば十分です。無理に付けると表記ゆれの原因になるため、「絞り込みに使うか」を基準に決めます。

SemVer(セマンティックバージョニング)との連携

Conventional Commitsが評価される最大の理由が、SemVer(MAJOR.MINOR.PATCH)との対応関係です。typeを機械が読むことで、次のバージョンを自動で判定できます。

コミット 上がる桁
fix PATCH 1.2.3 → 1.2.4
feat MINOR 1.2.3 → 1.3.0
破壊的変更(! / BREAKING CHANGE) MAJOR 1.2.3 → 2.0.0

この対応があるため、リリース時に「今回はMINORか、PATCHか」を人が判断する必要がなくなります。前回のタグ以降のコミットを走査し、feat が1件でもあればMINOR、破壊的変更があればMAJOR、fixだけならPATCHと機械的に決まります。バージョン付けの属人性とヒューマンエラーを同時に減らせるのが実務上の価値です。

導入手順とツール(commitlint・husky・commitizen)

Conventional Commitsは規約なので、守るかどうかは人任せになりがちです。実運用では、フォーマットを機械で強制し、リリースまで自動化するツールを組み合わせます。

commitlint+huskyでフォーマットを強制する

もっとも一般的な構成が、コミットメッセージを検証する commitlint と、Gitフックを管理する husky の組み合わせです。規約違反のメッセージをコミット時点で弾けます。

npm install --save-dev @commitlint/cli @commitlint/config-conventional husky

# commitlint.config.js
module.exports = { extends: ['@commitlint/config-conventional'] };

# husky でコミット時に検証(husky v9 以降)
npx husky init
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg

これで git commit のたびに .husky/commit-msg フックが commitlint を呼び、feat: などの形式に沿わないメッセージはコミットが中断されます。CIでも同じ検証を回しておくと、ローカルでフックを外したコミットも取りこぼしません。CI側の構成はGitHub Actionsでビルド・自動テストを設定する方法が参考になります。

commitizenで対話式にメッセージを作る

フォーマットを覚えきれないメンバーがいる場合は、commitizen が有効です。git cz を実行すると、typeやscopeを選択肢から選ぶ対話形式でメッセージを組み立てられ、規約に沿った文字列を自動生成します。導入初期の学習コストを下げる用途に向いています。

semantic-releaseでリリースを自動化する

コミットが規約に沿っていれば、semantic-release や standard-version でリリースまで自動化できます。前回リリース以降のコミットを解析してSemVerのバージョンを決定し、タグ付け・CHANGELOG生成・パッケージ公開までをパイプラインで実行します。CI/CDへの組み込み方はGitHubとCI/CDツールの統合のメリットGitHub Actionsの活用例とあわせて設計すると、手動リリースの手間を大きく削減できます。

導入すべきでない場面と失敗パターン

Conventional Commitsは万能ではありません。効果が出るのは「コミット履歴を自動化の入力に使う」プロジェクトで、そうでない場合はコストが上回ります。次のケースでは導入を見送るか、簡略版に留める判断が妥当です。

  • 個人開発・短期の使い捨てプロジェクト:リリースノート自動生成やSemVer運用をしないなら、形式を守る手間だけが残る。
  • チームがtypeの基準を共有していない:feat/fix/refactorの線引きが人によってブレると、履歴の一貫性が崩れ、かえって信頼できないリリースノートになる。導入時にscope一覧とtypeの判断基準をドキュメント化してから始める。
  • ツール検証を強制していない:規約を口頭ルールに留めると必ず逸脱が混ざる。commitlintで機械強制するのが前提で、それ抜きの「気をつける」運用は長続きしない。

逆に、複数人でメンテナンスし、定期リリースやライブラリ公開を行うプロジェクトでは、導入コストを短期間で回収できます。判断軸は「コミット履歴を機械に読ませたいか」の一点です。

よくある質問(FAQ)

Conventional Commitsの読み方は?

「コンベンショナル・コミット」です。Conventionalは「規約に基づいた」という意味で、「カンバセーショナルコミット」は誤読です。どちらで検索しても同じ規約を指します。

typeはfeat・fix以外に何がありますか?自由に増やせますか?

docs・style・refactor・perf・test・build・ci・chore・revert が慣習的な標準です。プロジェクト独自のtypeを追加することも可能ですが、増やしすぎると判断が曖昧になるため、commitlintの設定に登録して最小限に絞るのが安全です。

破壊的変更(BREAKING CHANGE)はどう書きますか?

typeの直後に ! を付ける(例:feat(api)!: ...)か、フッターに BREAKING CHANGE: と続けて説明を書きます。どちらもSemVerのMAJORバージョンを上げるトリガーになります。

コミットメッセージは日本語で書いてもいいですか?

仕様上、description やボディの言語に制限はなく日本語でも問題ありません。ただし type は feat・fix などの英単語で固定し、ツールが解釈できる形を保ちます。チーム内で言語を統一しておくと履歴が読みやすくなります。

小規模なプロジェクトでも使うべきですか?

必須ではありません。リリースノート自動生成やSemVer運用を行わない個人開発・短期プロジェクトでは、形式順守のコストが利点を上回ることがあります。自動化を前提とするチーム開発から導入するのが効果的です。

関連記事

資料請求

RELATED POSTS 関連記事