conventional-changelog について
conventional-changelogは、Conventional Commitsの書き方と、変更履歴やリリースバージョンを管理するツールを解説するスキルです。言語やリポジトリ構成、公開手順に合ったリリースワークフローの選定に役立ちます。
主な機能
- 01Conventional Commitsのガイド
- 02変更履歴ツールの比較
- 03リリース設定例
- 04Semverとタグの運用
- 05モノレポのリリース案内
活用シーン
- 01リポジトリのリリースフロー設定
- 02変更履歴の生成自動化
- 03言語やモノレポ向けツールの選定
- 04段階的なプレリリースの計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mizchi/ skills --skill conventional-changelogインストール後、Claude Code で/conventional-changelogを入力して読み込まれたか確認します。
同梱ファイルREADME.mdSKILL-ja.md
詳細
Conventional Changelog
Conventional Commits 仕様に従ったコミットメッセージの書き方と、そこから CHANGELOG と semver タグを機械的に生成する方法を紹介します。npm/cargo/python/rust/go のツールを選び、CHANGELOG を手作業で書かずに済むようにしましょう。
使用する場面
- 新しいリポジトリでリリースフローを設定するとき
- 既存リポジトリのコミットメッセージに一貫性がなく、CHANGELOG の生成を導入したいとき
- release-please を試したものの合わなかった、または代替手段を評価したいとき
- 言語(Rust/Python/Go など)に適した changelog ツールを探しているとき
- タグや CHANGELOG の手動運用で問題が繰り返し発生し、自動化したいとき
Conventional Commits の形式
形式:<type>[optional scope]: <subject>
feat(api): add rate-limit middleware
fix(auth): reject expired tokens before DB lookup
docs: clarify OAuth flow diagram
chore: bump deps
type の一覧と semver への影響
| type | semver の更新 | CHANGELOG への掲載 |
|---|---|---|
feat | minor | ✓(追加/機能) |
fix | patch | ✓(修正) |
perf | patch | ✓(変更) |
refactor | なし | ×(デフォルト) |
docs | なし | × |
style | なし | × |
test | なし | × |
build | なし | × |
ci | なし | × |
chore | なし | × |
revert | 取り消したコミットによる | ✓ |
破壊的変更(major 更新)
方法は 2 つあります。フッターに BREAKING CHANGE: を記載するか、type の後に ! を付けます。
feat(api)!: replace REST endpoint with GraphQL
BREAKING CHANGE: /api/v1/users is removed. Use GraphQL Query.user instead.
両方を記載すると親切です(タイトルで明確に示し、フッターで詳細を説明できます)。
scope
省略可能ですが、指定すると CHANGELOG が読みやすくなります。モノレポでは、パッケージ名を scope として使います。
feat(@pkg/auth): add oauth2 flow
feat(@pkg/billing): stripe migration
release-please は、scope から「変更対象のパッケージ」も自動検出します(manifest モードの場合)。
subject
- 小文字で始めます(末尾にピリオドを付けません)
- 命令形にします(「add X」/「fix Y」。「added」や「fixes」は避けます)
- 50 文字以内を目安にします
body/footer
空行の後に body を記載し、さらに空行を挟んで footer を記載します(Closes #123、Co-authored-by: ...、BREAKING CHANGE: ...)。
CHANGELOG.md の形式(Keep a Changelog)
keepachangelog.com に準拠します。バージョンを降順で並べ、semver を使用し、固定の 6 セクションを設けます。
# Changelog
All notable changes to this project are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- foo bar
## [1.2.0] - 2026-04-19
### Added
- New `--json` output flag for `foo scan` ([#42](https://github.com/owner/repo/pull/42))
### Changed
- `parse_config` now accepts YAML in addition to TOML
### Fixed
- Crash when config file is empty ([#40](https://github.com/owner/repo/issues/40))
### Deprecated
- `--legacy-mode` flag. Use `--mode=legacy` instead.
### Removed
- `foo bar --old-flag` (deprecated in 1.0.0)
### Security
- Upgrade `openssl` to 3.2.0 to address CVE-2025-XXXXX
## [1.1.0] - 2026-03-01
...
[Unreleased]: https://github.com/owner/repo/compare/v1.2.0...HEAD
[1.2.0]: https://github.com/owner/repo/compare/v1.1.0...v1.2.0
6 つのセクション:
Added:新機能Changed:既存機能の変更Deprecated:削除予定の機能(まだ存在するもの)Removed:削除済みの機能Fixed:バグ修正Security:脆弱性の修正
semver タグの運用
- タグは
v<MAJOR>.<MINOR>.<PATCH>の形式にします(v1.2.3)。vの接頭辞を付けるのが一般的です - プレリリース:
v1.0.0-beta.1/v1.0.0-rc.1 git tag -a v1.2.3 -m "Release v1.2.3"(注釈付きタグ)→git push origin v1.2.3on: releaseを使い、GitHub Release と Actions でタグの作成とデプロイを連携します
ツールの比較
| ツール | 対応言語 | 形式 | CHANGELOG の生成 | バージョン更新 | 主な強み | 弱点 |
|---|---|---|---|---|---|---|
| release-please | npm/python/rust/go/java/php/ruby | リリース PR を自動作成 | ✓ | ✓(PR のマージ時にタグ付け) | モノレポに対応し、Google が保守する安定したプロジェクト | PR ベースのため、習得に時間がかかる |
| changesets | npm のみ | changeset add で手動入力 | ✓ | ✓ | モノレポに対応し、柔軟(npm workspaces) | コミット駆動ではない |
| conventional-changelog-cli | 言語を問わない(コマンド) | コミットから一括生成 | ✓ | × | 軽量で、既存の CHANGELOG に追記できる | タグ/バージョン更新は別途手動で対応 |
| standard-version(非推奨) | npm | コミット → バージョン更新+CHANGELOG | ✓ | ✓ | シンプル | 保守終了。release-please への移行を推奨 |
| git-cliff | 言語を問わない(Rust で実装) | TOML 設定で高度にカスタマイズ可能 | ✓ | × | 高速で、柔軟なテンプレートを備え、Rust エコシステムで人気 | タグ/バージョン更新は別途対応 |
| towncrier | Python | PR ごとにニュースフラグメントを作成 | ✓ | × | フラグメントによりマージコンフリクトを回避 | 独特なワークフロー |
| auto(intuit/auto) | 複数 | ラベルベース+CI 連携 | ✓ | ✓ | GitHub ラベルを基盤とする | 独自のラベル規約が必要 |
1 行でわかるおすすめ
- 単一の npm パッケージを自動化したい → release-please
- npm モノレポ → release-please(マニフェストモード)または changesets(細かく制御したい場合)
- Rust → git-cliff
- Python → towncrier(または release-please)
- Go/汎用 → git-cliff または release-please
- CHANGELOG の生成だけを行いたい(タグ管理は手動) → conventional-changelog-cli または git-cliff
release-please のセットアップ(最もおすすめの方法)
npm プロジェクトでの新規セットアップ:
// release-please-config.json
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"release-type": "node",
"packages": {
".": { "package-name": "my-pkg", "changelog-path": "CHANGELOG.md" }
},
"include-v-in-tag": true,
"bump-minor-pre-major": true
}
// .release-please-manifest.json
{ ".": "0.0.0" }
# .github/workflows/release-please.yml
name: release-please
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v5
with:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
Conventional Commits の仕様に従ってコミットを作成し、main にプッシュすると、「Release PR」が自動的に作成されます。これをマージすると、タグの作成、GitHub Release、CHANGELOG の更新が実行されます。
公開に連動するワークフローの 2 つの形式:
| 形式 | トリガー | 長所 | 短所 |
|---|---|---|---|
同じワークフロー内でジョブを分離(needs: release-please + if: outputs.release_created) | push: main | 1 つのファイルで完結し、release-please の出力を直接参照でき、理解しやすい | release-please のジョブが失敗すると公開にも影響し、役割が混在する |
別のワークフロー(on: release) | release: { types: [published] } | 関心事を分離でき、手動リリースでも公開が実行され、再実行も独立している | シークレット/権限を 2 か所で宣言する必要があり、release-please の出力は利用できない |
選択の指針:公開先が 1 つ(npm のみ)の単一パッケージでは、1 つのワークフローにまとめると簡潔です。公開先が複数(npm + GitHub Container Registry など)ある場合や、手動リリースも許可する場合は、別の on: release ワークフローを使用してください。OIDC Trusted Publishing を使用する場合、id-token: write は公開ジョブだけに付与すれば十分で、どちらの形式でも機能します。
詳細については、npm-release スキル(ローカル管理)の公開フローを参照してください。
プレリリース(beta/rc)の段階的リリース
破壊的変更を含む v2.0.0 を beta → rc → stable の順にリリースする場合は、release-please の prerelease/prerelease-type フラグを使用します。
// release-please-config.json
{
"packages": {
".": {
"package-name": "my-pkg",
"prerelease": true,
"prerelease-type": "beta"
}
}
}
流れ:
prerelease-type: "beta"を指定してコミットを積み重ねる →v2.0.0-beta.1が作成されます- さらにコミットを積み重ねると
v2.0.0-beta.2/beta.3... となります - RC に昇格するには、設定を
"prerelease-type": "rc"に書き換えます →v2.0.0-rc.1 - 安定版をリリースするには、
"prerelease": falseを指定する(またはフィールドを削除する)→v2.0.0
CHANGELOG の記述方法:release-please は beta/rc ごとに独立したセクションを確定します([Unreleased] に変更を蓄積する Keep a Changelog 形式ではありません)。[2.0.0-beta.1]/[2.0.0-beta.2]/[2.0.0-rc.1]/[2.0.0] はすべて残ります。安定版の 2.0.0 セクションには、その期間中のすべての feat!/BREAKING CHANGE が集約されます。
モノレポと workspace:* の連携
@org/ui と @org/cli が @org/core に依存する pnpm ワークスペースの場合:
// release-please-config.json
{
"plugins": [
{ "type": "node-workspace", "updatePeerDependencies": true }
],
"packages": {
"packages/core": {
"release-type": "node",
"package-name": "@org/core",
"include-component-in-tag": true
},
"packages/ui": {
"release-type": "node",
"package-name": "@org/ui",
"include-component-in-tag": true
},
"packages/cli": {
"release-type": "node",
"package-name": "@org/cli",
"include-component-in-tag": true
}
},
"separate-pull-requests": false,
"include-v-in-tag": true
}
include-component-in-tag: true→ タグ名に@org/core-v2.0.0のようにコンポーネント名が含まれます(モノレポ内の衝突を回避します)node-workspaceプラグイン →@org/coreのバージョン更新を検出し、@org/ui/@org/cliのdependencies."@org/core"を書き換えて、両方のパッケージを PR でパッチバージョン更新として追加しますupdatePeerDependencies: true→ ピア依存関係も同様に書き換えます(ライブラリ側で必要です)separate-pull-requests: false→ すべてのパッケージの更新を 1 つの Release PR にまとめます
コミットのスコープにパッケージ名を含める:
feat(@org/core): add streaming parser
fix(@org/ui): button focus ring on safari
feat(@org/cli)!: rename --config to --profile
スコープによって変更の対象が自動的に決まります。該当パッケージの CHANGELOG にのみ項目が記載されます。
workspace:* の置換の仕組み:@org/ui/package.json に "@org/core": "workspace:*" と記述しても、pnpm は公開時にこれを ^<actual version> に自動的に置き換えます。release-please はバージョン更新時に workspace:* をそのまま維持し、変更しません。この前提は完全に一致しています(pnpm 側では、workspace:^ → ^same-major、workspace:~ → ~same-minor となります)。
git-cliff のセットアップ(Rust/汎用)
cargo install git-cliff
# or
brew install git-cliff
# cliff.toml
[changelog]
header = "# Changelog\n"
body = """
{% if version %}## [{{ version }}] - {{ timestamp | date(format="%Y-%m-%d") }}{% endif %}
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }} ({{ commit.id | truncate(length=7, end="") }})
{% endfor %}
{% endfor %}
"""
[git]
conventional_commits = true
filter_unconventional = true # Exclude existing non-conforming commits from the CHANGELOG
protect_breaking_commits = true
commit_parsers = [
{ message = "^feat", group = "Added" },
{ message = "^fix", group = "Fixed" },
{ message = "^perf", group = "Changed" },
{ message = "^refactor", group = "Changed" },
{ message = "^deprecat", group = "Deprecated" },
{ message = "^remove", group = "Removed" },
{ message = "^security", group = "Security" },
{ message = "^revert", group = "Reverted" },
{ message = "^(docs|style|test|build|ci|chore)", skip = true },
{ message = ".*", skip = true }, # Bulk-exclude non-conforming commits (do not rewrite history)
]
tag_pattern = "v[0-9]*"
sort_commits = "newest"
cargo-release と併用する Rust プロジェクトでは、cargo-release が Cargo.toml のバージョン更新とタグ付けを担当し、git-cliff は CHANGELOG の生成だけに専念します(疎結合です)。このため、release-please のような PR ベースの自動更新をさらに重ねることはありません。
git-cliff --output CHANGELOG.md # Regenerate from full history
git-cliff --unreleased --prepend CHANGELOG.md # Prepend only the unreleased section
git-cliff --tag v1.2.0 --output CHANGELOG.md # Generate for a specific tag
cargo-release との連携(具体例)
Cargo.toml の [package.metadata.release] にフックを設定します。cargo release <level> を実行すると、バージョン更新 → CHANGELOG 生成 → コミット → タグ付け → プッシュの順に処理されます。
# Cargo.toml
[package.metadata.release]
# After the version bump and before the commit, update CHANGELOG with git-cliff
pre-release-hook = ["git", "cliff", "--tag", "v{{version}}", "--unreleased", "--prepend", "CHANGELOG.md"]
# The tag itself is created by cargo-release
tag-name = "v{{version}}"
# Include CHANGELOG.md in the release commit
pre-release-commit-message = "chore(release): v{{version}}"
順序:
cargo release minor --execute→Cargo.tomlのバージョンを更新pre-release-hookがgit cliffを実行し、次のバージョンの[Unreleased]を[v0.2.0] - 2026-04-19として確定して、CHANGELOG.mdを更新- cargo-release が
Cargo.tomlとCHANGELOG.mdをリリースコミットにまとめる tag-nameが注釈付きタグとしてv0.2.0を作成cargo publish+git push --tags
注:git-cliff 側の [changelog.bump] セクション(features_always_bump_minor など)は、git-cliff 自身がバージョン更新を決定する git-cliff 固有の機能です。cargo-release と併用する場合は使わないでください(バージョン更新の決定は cargo-release が担当します)。<level>(patch/minor/major)は人が選択します。
conventional-changelog-cli(軽量、言語非依存)
npm install -g conventional-changelog-cli
conventional-changelog -p angular -i CHANGELOG.md -s -r 0
# -p: preset (angular / atom / ember / eslint / jquery / jshint)
# -i: input, -s: same file, -r 0: full history
主なプリセットは angular です(Conventional Commits の由来です)。既存の CHANGELOG への追記に適しています。
pre-commit によるコミットメッセージの検証
コミット時に Conventional Commits の仕様に違反するコミットを拒否します。
commitlint
npm install -D @commitlint/cli @commitlint/config-conventional
// commitlint.config.js
module.exports = { extends: ['@commitlint/config-conventional'] };
# .pre-commit-config.yaml (pre-commit framework)
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.16.0
hooks:
- id: commitlint
stages: [commit-msg]
additional_dependencies: ['@commitlint/config-conventional']
注意点:additional_dependencies がないと、フックは実行時に config-conventional を解決できず、Cannot find module エラーで失敗します。commitlint.config.js で extends を指定するだけでは不十分です。フックの分離された環境でも明示的に宣言する必要があります。
mizchi-default pkfire エコシステムでは、commitlint は代わりに Taskfile.pkl タスクに組み込まれています。chezmoi-management と pkfire のスキルを参照してください。
commitizen(対話形式でのコミット作成)
npm install -D commitizen cz-conventional-changelog
# package.json
"config": { "commitizen": { "path": "./node_modules/cz-conventional-changelog" } }
# usage
git cz
よくある失敗
- コミット規約を途中から導入する:既存の履歴は不正な形式のままです。release-please はスキャン時に「規約に準拠していないコミット」を無視します。遡って書き換える必要はありません。今後の分から規約に合わせてください
- リリース PR が作成されないよう、すべてに
chore:を使う:バグ修正にchore:と書くと、CHANGELOG に記載されず、バージョンも更新されません。重要度ではなく「変更の種類」でタイプを選んでください(fix はユーザーに見える修正、chore は内部的な雑務です) - サブジェクトに BREAKING CHANGE と書き、フッターを省略する:release-please は、フッターの
BREAKING CHANGE:またはタイプの!を確認します。サブジェクトに「breaking: ...」と書いても、メジャーバージョンの更新は発生しません - 手動での CHANGELOG 編集とツールを併用する:release-please が管理する CHANGELOG を手動で編集すると、次回生成時に内容にずれが生じます。エントリーは PR 経由でのみ追加してください(release-please の「編集」機能を使います)
- 先にタグを作成してから release-please の PR を開く:release-please は PR のマージ時にタグを作成します。手動で作成したタグは競合します。手動で運用する場合は、conventional-changelog-cli/git-cliff と手動タグ付けの組み合わせに統一してください
注意すべき点
| よくある考え | 実際のところ |
|---|---|
| 「CHANGELOG を手書きしたほうが、より洗練される」 | コミットから生成すれば、見落としがありません。手書きでは、必ず抜け漏れや表現の不統一が生じます |
| 「先にタグを作成してから、変更履歴を書く」 | 順序が逆です。コミット → ツールで CHANGELOG を生成 → タグ、の順にします |
| 「破壊的変更は、件名に書けば明確になる」 | ツールはフッターまたは ! を機械的に読み取ります。件名の自然言語による表現は無視されます |
| 「プロジェクト固有のタイプを追加しよう」 | feat / fix / chore の範囲内で表現できます。ツールのプリセットでは、独自のタイプはサポートされていません |
| 「規約に沿わないコミットは、rebase で修正しよう」 | 過去に遡って書き換えると、履歴が汚れます。今後のコミットから規約に合わせればよく、ツールはそれ以外を無視します |
関連項目
npm-release— release-please + OIDC Trusted Publishing によって、公開までをすべて自動化します(セッション固有のローカル管理)apm-usagereferences/publishing.md — スキルの公開時における CHANGELOG の規約gh-fix-ci— リリースワークフローが CI で失敗した場合- Keep a Changelog:https://keepachangelog.com/
- Conventional Commits:https://www.conventionalcommits.org/
- release-please:https://github.com/googleapis/release-please
- git-cliff:https://git-cliff.org/