mcpField
C
conventional-changelog

conventional-changelog

github.com/mizchi開発41668 回インストール1 週間前に更新
リポジトリ

conventional-changelog について

conventional-changelogは、Conventional Commitsの書き方と、変更履歴やリリースバージョンを管理するツールを解説するスキルです。言語やリポジトリ構成、公開手順に合ったリリースワークフローの選定に役立ちます。

主な機能

  1. 01Conventional Commitsのガイド
  2. 02変更履歴ツールの比較
  3. 03リリース設定例
  4. 04Semverとタグの運用
  5. 05モノレポのリリース案内

活用シーン

  1. 01リポジトリのリリースフロー設定
  2. 02変更履歴の生成自動化
  3. 03言語やモノレポ向けツールの選定
  4. 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 への影響
typesemver の更新CHANGELOG への掲載
featminor✓(追加/機能)
fixpatch✓(修正)
perfpatch✓(変更)
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.3
  • on: release を使い、GitHub Release と Actions でタグの作成とデプロイを連携します

ツールの比較

ツール対応言語形式CHANGELOG の生成バージョン更新主な強み弱点
release-pleasenpm/python/rust/go/java/php/rubyリリース PR を自動作成✓✓(PR のマージ時にタグ付け)モノレポに対応し、Google が保守する安定したプロジェクトPR ベースのため、習得に時間がかかる
changesetsnpm のみchangeset add で手動入力✓✓モノレポに対応し、柔軟(npm workspaces)コミット駆動ではない
conventional-changelog-cli言語を問わない(コマンド)コミットから一括生成✓×軽量で、既存の CHANGELOG に追記できるタグ/バージョン更新は別途手動で対応
standard-version(非推奨)npmコミット → バージョン更新+CHANGELOG✓✓シンプル保守終了。release-please への移行を推奨
git-cliff言語を問わない(Rust で実装)TOML 設定で高度にカスタマイズ可能✓×高速で、柔軟なテンプレートを備え、Rust エコシステムで人気タグ/バージョン更新は別途対応
towncrierPythonPR ごとにニュースフラグメントを作成✓×フラグメントによりマージコンフリクトを回避独特なワークフロー
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: main1 つのファイルで完結し、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"
    }
  }
}

流れ:

  1. prerelease-type: "beta" を指定してコミットを積み重ねる → v2.0.0-beta.1 が作成されます
  2. さらにコミットを積み重ねると v2.0.0-beta.2/beta.3 ... となります
  3. RC に昇格するには、設定を "prerelease-type": "rc" に書き換えます → v2.0.0-rc.1
  4. 安定版をリリースするには、"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}}"

順序:

  1. cargo release minor --execute → Cargo.toml のバージョンを更新
  2. pre-release-hook が git cliff を実行し、次のバージョンの [Unreleased] を [v0.2.0] - 2026-04-19 として確定して、CHANGELOG.md を更新
  3. cargo-release が Cargo.toml と CHANGELOG.md をリリースコミットにまとめる
  4. tag-name が注釈付きタグとして v0.2.0 を作成
  5. 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 で修正しよう」過去に遡って書き換えると、履歴が汚れます。今後のコミットから規約に合わせればよく、ツールはそれ以外を無視します

関連項目

コメント