セマンティックバージョニングとあなたのチェンジログ
1分で読めます
セマンティックバージョニングは、呼び出し側が一つのチェンジログのエントリを読む前に、リリースがどれだけ痛みを伴うかを伝える。2.4.1から2.5.0への移行はこう言っている。新しい機能、何も壊れない。2.5.0から3.0.0への移行はこう言っている。アップデートの前にこのエントリを読め。チェンジログとバージョン番号は二つの形式で同じことを主張するはずであり、両者の間の摩擦のほとんどは、まさに両者が一致しないときに現れる。それは仕様が示唆するよりも頻繁に起こる。
バージョンの各番号は実際には何を約束しているのか
セマンティックバージョニングは三つの番号を定義する。MAJOR.MINOR.PATCH、それぞれに何がそれを引き起こすかについての厳格な規則がある。MAJORの跳躍は互換性のない変更を意味する。正しい既存の統合が気づく可能性があり、そのために変更しなければならない何かだ。MINORの跳躍は新しい、後方互換性のある機能を意味する。既存のものは何も壊れず、新しい何かが利用可能になる。PATCHの跳躍は後方互換性のある修正を意味する。挙動は文書化されていたものに近づき、意図的に古い挙動に依存していた誰も何も気づくべきではない。
| 跳躍 | 意味 | エントリはこう読めるべき |
|---|---|---|
MAJOR (1.x.x -> 2.0.0) | 互換性のない変更 | 「アップデート前に対応が必要」 |
MINOR (1.2.x -> 1.3.0) | 新しい互換性のある機能 | 「今から利用可能、他は何も変わらない」 |
PATCH (1.2.3 -> 1.2.4) | 互換性のある修正 | 「文書化された通りに振る舞うようになった」 |
この表は逆方向のテストでもある。エントリがその行のように読めないなら、バージョン番号が間違っているか、エントリが実際に起きたことを過小または過大に売り込んでいるかのどちらかだ。
バージョニングの目的上、何が互換性のないものとして数えられるのか
何かがAPIチェンジログに属するかどうかを決めるのと同じテストだ。古い挙動に対して書かれ、それ以来触れられていない正しい呼び出し側が、この変更のせいで違う振る舞いをする可能性があるかどうか。互換性のない変更とは何か、それをどうリリースするかがその判断を完全に扱っており、互換性がないように見えてそうでない場合や、小さく見えてそうでない場合も含む。バージョニングの目的上、簡単に言えば、答えがイエスなら、変更が内部で実際にどれだけのコードに触れたかにかかわらず、跳躍はMAJORだ。バージョン番号は、チームの労力ではなく、呼び出し側にとっての結果を追跡する。
チェンジログのエントリはバージョンの跳躍にどう対応すべきか
一つのエントリ、一つの跳躍カテゴリを、最初にはっきりと述べる。表のパターンはそのまま続く。互換性のないエントリは、それを導入したバージョンの下に置かれ、まず警告として、次に説明として表現される。追加のエントリはそのMINORバージョンの下に置かれ、利用可能性として表現される。修正はそのPATCHバージョンの下に置かれ、訂正として表現される。一つのエントリの中でカテゴリを混ぜること、たとえば互換性のない変更を無関係な修正と同じ段落に折り込むことは、読者が本当に重要だったまさにその一点を見逃してしまう原因になる。
## 3.0.0 (2026-09-07)
### Changed
- **BREAKING:** `GET /reports`は金額を小数ではなく、最小通貨単位(セン
ト)の整数として返すようになった。`amount`を直接読むコードを更新する
こと。
## 2.9.0 (2026-09-01)
### Added
- レポートは`status`でフィルタできるようになった。
## 2.8.4 (2026-08-28)
### Fixed
- `GET /reports?status=`は、未知のステータスに対して400ではなく空のペ
ージを返していた。
上から下に読むと、バージョン番号とセクションラベルは同じことを二度言っている。まさにそれが目的だ。見出しだけをざっと見る読者でも、一行も開かないうちに正しいリスクの読み取りが得られる。
破壊的変更のルールは1.0.0より前でも同じように適用されるか
いいえ、そしてここにこそ「それは本当に破壊的変更だったのか」をめぐる混乱の大半の原因がある。SemVerは、メジャーバージョンゼロ、つまり0.y.zが初期開発のためのものであり、いつでも何でも変わりうるし、公開APIは安定していると見なすべきではないと明言している。0.4.0から0.5.0への引き上げは、仕様に違反することなく破壊的変更を運ぶことができる。メジャーバージョンの保証はプロジェクトが1.0.0を出荷して初めて始まるからだ。それでもチェンジログのエントリは、何が壊れたかについて読者に同じ正直さを負っている。変わるのは、1.0.0に達するまではバージョン番号自体が頼るべき信号ではないという点だけだ。
あなたの製品が個別のバージョンをリリースしない場合はどうか
ほとんどのSaaS製品は継続的にデプロイされ、呼び出し側にバージョン番号を見せることは決してない。これはこの規律の必要性をなくすわけではなく、通常それを運ぶ番号をなくすだけだ。チェンジログのエントリはすべての仕事を単独で行わなければならない。変更が互換性のないものか、追加的なものか、修正なのかを、セマンティックバージョニングが使うのと同じ三つの単語で、それを付けるバージョンフィールドがなくてもはっきりと述べる。一部のチームは、チェンジログのエントリをリンクできる何かに固定するためだけに、呼び出し側に直接見せることなく、純粋に内部的なバージョンを維持している。
これはAPIチェンジログに特にどう当てはまるのか
ほとんどどこよりも厳格に、なぜならAPIの呼び出し側はコードであり、予期しない変更に肩をすくめられる人間ではないからだ。APIチェンジログ: 何を公開し、誰が読むのかがその文書の完全な形を扱っている。ここでのバージョニングの規律は、そのbreakingとadditiveのセクションを誠実に保つものだ。移行期間中にv1とv2を並行して提供するような、複数のバージョンを同時に提供するAPIは、事実上、一つのパッケージではなくインターフェース全体の規模でセマンティックバージョニングを適用している。そして同じ三語の語彙が依然としてすべてのエントリに当てはまる。
Keep a Changelogはバージョニングについて何と言っているか
それは名前によって直接セマンティックバージョニングと結びついており、この記事が使っているのと同じカテゴリの語彙を推奨している。Added、Changed、Deprecated、Removed、Fixed、Security。Keep a Changelog、実践編がその仕様をどう採用するかを、チームがそこからよく外れる箇所も含めて扱っている。この重なりは偶然ではない。両方の仕様は、対極から同じ問題を解決しようとしている。一方はバージョン番号を標準化し、もう一方はそれを説明するエントリを標準化する。
FAQ
すべてのチェンジログのエントリにバージョン番号が必要か? 製品がバージョンをリリースするなら必要だ。番号によって読者はエントリを先に読まずに「これがどれだけ自分に影響するか」に直接ジャンプできるからだ。製品がバージョンフィールドなしで継続的にデプロイされるなら、エントリの表現がその信号を単独で運ばなければならない。
MAJORの跳躍と互換性のない変更のエントリの違いは何か? それらは同じ出来事を二つの方法で説明すべきだ。バージョン番号は機械が読める信号であり(呼び出し側のツールがそれに反応できる)、チェンジログのエントリは具体的に何が変わったかについての人間が読める説明だ。
PATCHリリースが互換性のないものになりうるか? 定義上、なるべきではない。それでも出荷してしまった場合は、公開済みのバージョンを編集したり、タグを付け直したりしてはいけない。SemVerのFAQは、互換性を回復する新しいバージョンをリリースするか、互換性のない変更を残すなら新しいMAJORをリリースし、問題のバージョンを文書化して利用者がそれを飛ばせるようにすることを求めている。
純粋に内部的な変更にバージョンの跳躍が必要か? 不要だ。セマンティックバージョニングは公開インターフェースを追跡する。呼び出し側にとって観測可能な効果のないリファクタリングは、たとえ内部的に重要なエンジニアリング作業であっても、跳躍もチェンジログのエントリも必要としない。
この記事の技術的な記述は第三者による確認を受けていません。誤りがあればお知らせください。修正します。