ソフトウェアのバージョン番号には、実はSemVerだけではなく多種多様な戦略があります。開発者の多くは日々「バージョンをいくつに上げるべきか?」と悩むことがあるでしょう。ここでは、代表的なものからユニークなものまで、18種類のバージョニング戦略についてそれぞれの特徴をまとめます。最初に簡易比較表を、その後に詳細な解説を掲載します。
バージョニング戦略 簡易比較表
戦略名 | 命名規則 | 互換性表示 | ソート可能 |
---|---|---|---|
SemVer | MAJOR.MINOR.PATCH |
✓ | ✓ |
CalVer |
YYYY.MM.DD (日付形式) |
✗ | ✓ |
ZeroVer | 0.y.z |
✗ | ✓ |
EffVer | Macro.Meso.Micro |
△ | ✓ |
RomVer | HUMAN.MAJOR.MINOR |
△ | △ |
Sentimental | 作者が決めた形式 | ✗ | △ |
HashVer | YYYY.MM.DD.hash |
✗ | △ |
GitDate | YYYY.MM.DD.git-hash |
✗ | △ |
PragVer | BIGRELEASE.ANNOUNCE.INCREMENT |
△ | ✓ |
WendtVer |
A.B.C (0-9のカウンタ) |
✗ | ✓ |
SoloVer |
N または N-postfix
|
✗ | ✓ |
BreakVer | major.minor.non-breaking |
✓ | ✓ |
Explicit Versioning | Disruptive.Incompatible.Compatible.Fix |
✓ | ✓ |
ZenVer |
X (単一整数) |
✗ | ✓ |
PVP | A.B.C(.D...) |
✓ | ✓ |
FloatVer | 浮動小数点数 | ✗ | ✓ |
AsymptoVer | 定数に漸近する数値 | ✓ | ✓ |
TrunkVer | YYYYMMDDHHMMSS.0.0-hash-build |
✗ | ✓ |
凡例:
- 互換性表示: ✓=明確に表示、△=部分的/限定的に表示、✗=表示しない
- ソート可能: ✓=容易にソート可能、△=一部条件付きでソート可能
それでは各戦略について詳しく見ていきましょう。
SemVer(Semantic Versioning)
SemVer(セマンティック バージョニング)は最も広く使われているバージョン戦略の一つです。2010年にGitHub創設者のTom Preston-Werner氏によって提案され、事実上オープンソースコミュニティの標準となっています。npmやRubyGems、Cargoといった主要なパッケージ管理システムでも採用されており、もはやバージョニングと言えばSemVerと言っても過言ではありません。
概要
バージョン番号にソフトウェアの後方互換性の有無を明示し、開発者と利用者の双方に安心感を与えることを目的としています。変更内容の重要度に応じてバージョン番号を増分することで、アップデート時のリスクを直感的に伝える戦略です。
命名規則
MAJOR.MINOR.PATCH
という3つの整数で表記します。それぞれ以下の意味を持ちます:
- MAJOR(メジャー):後方互換性のない変更を行った場合に増やします。大きな機能追加やAPIの破壊的変更が該当します。
- MINOR(マイナー):後方互換性を保った機能追加を行った場合に増やします。新機能や改善で既存利用者への影響が小さいものです。
- PATCH(パッチ):後方互換性のあるバグ修正を行った場合に増やします。挙動は変えず不具合だけ修正する変更です。
自動バージョンアップ可能性: ✓
バージョン番号から互換性の有無が読み取れるため、ツールによる自動アップデート判断が可能です。例えば、依存関係を^1.2.3
のように指定すれば、MAJORが同じ範囲内(後方互換あり)での最新版へ自動更新できます。実際、npmやCargoではデフォルトでこのような範囲指定が利用されています。
ソート可能性: ✓
1.2.10 > 1.2.2 > 1.1.0
のように、各数値部分を順に比較することで時系列順やバージョンの高低を正しく並べ替えられます。標準的なバージョン比較アルゴリズムが確立されており、数字として扱えば順序付け可能です。
採用例
業界標準であり、Node.jsのnpmパッケージ、RubyGems(Rubyライブラリ)、RustのCargoクレートなど数え切れないほど多くのOSSでSemVerが使われています。メジャーバージョン0を脱して初めて「安定版」とみなす文化もSemVerによって広まりました。
公式ドキュメント: semver.org
CalVer(Calendar Versioning)
CalVer(カレンダー バージョニング)はバージョン番号にリリース年月日を取り入れる戦略です。例えば「2021.03.22」のようにYYYY.MM.DD形式でそのリリースの日付を表します。「このバージョンはいつ出たんだっけ?」と思うことがよくありますが、CalVerならバージョン名自体がカレンダーになっているので一目瞭然ですね。
概要
バージョン番号を見ればリリース時期が直感的に分かるようにするのが目的です。SemVerが変更の互換性に重点を置くのに対し、CalVerは日付でソフトウェアの新鮮さやリリース計画を伝えます。Mahmoud Hashemi氏によって2016年に提案されました。
命名規則
基本形式はYYYY.MM.DD
(年.月.日)ですが、プロジェクトに応じて様々なバリエーションがあります。例えば年と月のみのYYYY.MM
(例: 2021.03)や、週番号を使ったYYYY.WW
(例: 2021.12はその年の第12週)などです。ゼロ埋めをすることで文字列比較でも時系列順になる工夫も提案されています。
自動バージョンアップ可能性: ✗
バージョン名から互換性や破壊的変更の有無は読み取れません。CalVerはあくまで日付情報であり、互換性については別途ドキュメントやリリースノートを確認する必要があります。そのため、自動で「互換性があるからアップデートして良い」という判断はできません。
ソート可能性: ✓
年月日という性質上、時系列順に並べることが容易です。例えば2021.03.05
と2021.07.01
は、年と月で比較すれば順序を決定できます。ただしゼロ埋めをしていない形式(例えば21.3
vs 21.10
)だと文字列順が崩れる可能性があるため、推奨フォーマットではゼロ埋めして比較しやすくしています。
採用例
Ubuntuなどのリナックスディストリビューションが有名です。Ubuntuでは「年.月」でバージョンを付け(例: Ubuntu 18.04は2018年04月リリース)、半年ごとの定期リリースを明示しています。また、Pythonのパッケージ管理ツールpipも2018年にSemVerからCalVerに移行し、バージョン10の次を18.0とする飛び番アップデートを行いました。このように、CalVerはOSや開発ツールなどリリース時期が重要なプロジェクトで採用されています。
公式ドキュメント: calver.org
ZeroVer
ZeroVer(0ver、ゼロバージョン)はちょっと風変わりな戦略です。常にメジャーバージョンを0に留めるというジョークから生まれたバージョニングです。例えば1.0.0とは決して名乗らず、0.9.8の次も0.10.0(メジャーは0のまま)といった具合です。「ずっと未完成でごめんなさい」という自虐にも感じられますね。
概要
ソフトウェアの永遠のβ版宣言とも言えます。開発初期でAPIが不安定なうちは通常0.x.xを使いますが、ZeroVerでは意図的に常に0から始めることで「このソフトはまだ本番リリースの安定版ではない」という姿勢を示します。2018年4月1日にMahmoud Hashemi氏によって皮肉を込めて公開されました(エイプリルフールのジョークですね)。
命名規則
0.y.z
の形式で、メジャーは必ず0固定です。以降は通常の数値としてマイナーやパッチを増やしますが、1.0.0には決して到達しません。例えば0.1.0、0.2.0…と続け、仮に安定してきても0.10.0や0.99.0といったバージョンになります。
自動バージョンアップ可能性: ✗
互換性の指標としてのメジャー番号が常に0なので、バージョンから互換性を推測することはできません。そもそもすべてのリリースが「不安定で変化しうる」という前提なので、利用者側は常に注意が必要です。0.x版のソフトは破壊的変更が含まれる可能性がある、と心得ておく必要があります。
ソート可能性: ✓
通常の数値バージョンと同様、0.1.0 < 0.2.0 < 0.10.0 のように並べられます。メジャーが固定0のため比較軸が減りますが、マイナー・パッチで比較すれば順序付けは可能です。ただし、0.10.0と0.2.0のように桁数が異なる場合、文字列として単純比較すると順序が狂うので注意が必要です(数値比較なら問題ありません)。
採用例
ジョークとはいえ、意図せず長年0.xのままというプロジェクトは少なくありません。例えばHashiCorp VaultやTerraform、Apache Kafka、OpenSSLなどはリリースから長い期間メジャー0で開発が続けられた例です。ZeroVerは「メジャー1.0を切りたがらない心理」を風刺した側面もあり、現実にも多くのOSSが結果的にこの状態に陥っています。
公式ドキュメント: 0ver.org
EffVer(Intended Effort Versioning)
EffVer(エフバージョン、労力ベースのバージョニング)はユニークなアイデアで、アップグレードの手間を尺度にしたバージョン戦略です。バージョンを上げる際に「今回の変更は利用者にどれくらい影響を与えるだろう?」と考えるのが一般的ですが、EffVerはまさにその影響度(必要な対応労力)を直接バージョン番号に反映しようという試みです。
概要
変更内容の「重大度」ではなく、ユーザーが新バージョンを導入する際の労力に着目します。バグ修正か機能追加かといった技術的分類はせず、「既存ユーザーにとって対応が楽か大変か」でバージョン番号を決めるのが特徴です。2024年1月にJacob Tomlinson氏によって提案されました。
命名規則
基本はSemVerと同じく3つの番号ですが、意味付けが異なります。提案者はMacro(マクロ)・Meso(メソ)・Micro(マイクロ)という名称を使っています(以下、それぞれ大中小のニュアンスです)。ルールは次の通りです:
- Macro:大きな労力を要するアップデート時に増加。既存ユーザーが大幅な対応を強いられるような変更(例:全面的なAPI変更、大規模リファクタリング)でバージョンを上げます。
- Meso:ある程度の労力を要するアップデート時に増加。一部修正や注意が必要だが対応可能な変更(例:小さな非互換や挙動変更)で増やします。
- Micro:ほとんど労力が不要なアップデート時に増加。ユーザー対応不要が意図された変更(例:バグfixや軽微な機能追加)で上げます。
自動バージョンアップ可能性: △
バージョンから「アップデート対応の大変さ」を読み取れるため、Microレベルのアップデートであれば自動適用しても安全、と判断しやすくなります。ただしこれは開発者の意図に基づくものであり、実際に互換性が保たれる保証ではありません。意図と結果が食い違う可能性もある点には注意が必要です(それでも意図を示すだけユーザーへの敬意になる、というのが提唱者の考えです)。
ソート可能性: ✓
基本は数値の増分なのでSemVerと同様に数字比較で順序付け可能です。Macro→Meso→Microの順で番号が上がっていくため、時間経過に伴い単純に増加していきます。従って、例えば2.0.0(大変な変更)よりも2.1.0(やや小さい変更)の方が後に出た版でも、数値的には大きくなるので正しく比較できます。
採用例
まだ新しい提案ですが、JupyterHubプロジェクトがEffVerに従ったバージョニングを採用しています。JupyterHubでは、データベーススキーマの変更やPythonバージョン要件の引き上げといったユーザーに大きな対応を求める変更時にメジャー(Macro相当)を上げる運用をしています。このように、一部のプロジェクトで徐々に実践が始まっています。
公式ドキュメント: Jacob Tomlinsonブログ
RomVer(Romantic Versioning)
RomVer(ロマンティック バージョニング)は名前からしてユニークですが、人間にとって覚えやすい名前をバージョンに含める戦略です。例えば「Astro.2.5」のように、バージョン番号の前にコードネーム的な単語を付けるイメージです。Ubuntuのコードネーム(例: Focal Fossa)などがこれに似ていますが、RomVerではそれを正式なバージョン番号の一部にしてしまいます。
概要
SemVerをベースにしつつ、各リリースに印象的な名前(HUMAN要素)を付与することで、ユーザーにとってバージョンを覚えやすくしようとする戦略です。Node.jsやRails、Linuxカーネルなど様々なソフトの実例を調査し、「現場で自然と行われているバージョニングの工夫」を取り入れようとした試みです。2015年にDaniel V.氏によって提唱されました。
命名規則
HUMAN.MAJOR.MINOR
という3部構成を提案しています。例えば先頭に人間が覚えやすい単語(コードネームや愛称)を置き、その後にメジャー・マイナー番号を続けます。具体例としては:
- HUMAN:リリースの象徴となる単語。開発者にとって意味のあるニックネームやプロジェクトの節目を表す名前など、覚えやすいものを付けます。
- MAJOR:互換性のない大きな変更があった場合に増やす番号(SemVerのメジャーと同様)。
- MINOR:小規模な互換性維持の変更やバグ修正で増やす番号(SemVerのマイナー/パッチ相当)。
自動バージョンアップ可能性: △
MAJOR/MINORの部分は互換性を表すのでSemVer同様に扱えます。しかしHUMAN要素は文字列で、バージョンの大小関係や互換性には直接関与しません。一般にはHUMAN名が変わるとメジャーアップに対応する(つまり大きな変更)と期待できますが、機械的に判断するには一手間あります。とはいえ、MAJOR番号を見る限り互換性の可否は判断可能なので、自動アップデートの支援にはなります。
ソート可能性: △
年月や数値ではなく任意の単語を含むため、そのまま文字列比較すると期待する順序にならない可能性があります。例えばAstro.2.0
とBlossom.1.0
というバージョン名を単純比較すると"A" vs "B"で順序付けされてしまいます。実運用ではHUMAN部分を無視して数値部分で比較するか、あらかじめHUMAN名に順序を持たせる(アルファベット順など)必要があります。
採用例
正式にRomVerを採用しているOSSは多くありませんが、着想のもとになった例としてBackbone.js(Jeremy Ashkenas氏による2012年の言及)などがあります。また、多くのプロジェクトがメジャーリリースにコードネームを付ける慣習を持っています(Ubuntuのリリース名やAndroidのコードネームなど)。RomVerはそれをバージョン付け規則に昇華させた形と言えるでしょう。
公式ドキュメント: RomVer仕様 (GitHub)
Sentimental Versioning
Sentimental Versioning(センチメンタル バージョニング)はバージョン番号に作者の個人的な思い入れを反映させるという、遊び心あふれる戦略です。誕生日や好きな数字をバージョンにしたくなる気持ちもわかりますが、これを正式な方針にしてしまおうというのですから驚きです。
概要
既存の厳格な規約にとらわれず、作者の創意工夫や感情によってバージョンを決めます。例えば「他の誰とも被らないユニークな番号にする」「自分にとって意味のある数字の並びにする」といった、詩的・芸術的発想で番号を付けることを推奨しています。2014年8月にDominic Tarr氏が提唱しました。
命名規則
明確な形式はなく作者が美しいと感じる形で付けます。他人の方式を真似るのは禁止で、自分だけのオリジナルなバージョニング「システム」を作るよう求められます。必要であればその意味を後付けで説明しても良いし、その時の気分で番号を決めても良いとされています。要はルール無用ですが、「作者にとって特別」であることだけは重視します。
自動バージョンアップ可能性: ✗
互換性どころか数値的な増減ですら一貫している保証がありません。極端な話、前のバージョンより数字が小さい新バージョンが登場する可能性すらあります(作者の気分次第では「初心に戻る」と称して1.0から0.0に戻すことも?)。機械的な依存管理やアップデートにはまったく向かない戦略です。
ソート可能性: △
日付や通し番号に基づかないため、リリース順に並べるには各バージョンの発表日などメタ情報に頼る必要があります。バージョン文字列そのものから順序性を導くのはほぼ不可能です。
採用例
基本的にジョークや実験的な試みとして語られることが多く、主要なOSSで採用されている例は見当たりません。Dominic Tarr氏自身が関わるプロジェクトや、一部の趣味的なライブラリで一時話題になった程度です。「現実的ではないけれど、バージョン番号に自由を!」という思想的な側面が強く、実運用には不向きでしょう。
公式ドキュメント: Sentimental Versioning (GitHub)
HashVer(Hash Versioning)
HashVer(ハッシュ バージョニング)は、リリースごとにソースコード管理のコミットハッシュをバージョンに組み込む戦略です。開発者の多くはGitのコミットハッシュを見て変更を特定することがありますが、HashVerではそれをバージョン番号自体に含めてしまおうという発想です。
概要
高頻度でリリースする場合に適した戦略です。頻繁なリリースでは逐一セマンティックな意味を持つ番号を付けるのが難しくなりますが、HashVerならコミットIDで一意性が保証できます。日付と組み合わせることでいつ・どのコミットからビルドされたバージョンかがひと目で分かります。
命名規則
YYYY.MM[.DD].<commit-hash>
の形式を取ります。まず年・月(・必要に応じて日)を付け、その後にソース管理システムのコミットハッシュの先頭10文字以上を付与します。例えば次のようなバージョンになります:
-
2020.01.67092445a1abc
(2020年1月のある時点のコミット) -
2019.07.21.3731a8be0f1a8
(2019年07月21日の特定コミット)
ハッシュだけでは順序がランダムになるため、日付を前置するのがポイントです。日付以外にビルド番号を入れる方法も提案されています。
自動バージョンアップ可能性: ✗
バージョン名から互換性や変更の規模は判断できません。コミットハッシュは単なる識別子であり、例えば2020.01.xxxxx
から2020.02.yyyyy
に上がったとしても、それが大きな変更か小さな修正かは分からないのです。あくまで「いつ・どのコミット」かを示す技術的情報に留まります。
ソート可能性: △
基本は日付で並べればよいので時系列順にソート可能です。しかし同一日に複数リリースがある場合、ハッシュ部分では順序を保証できません。その場合はビルド番号や日時まで含めたタイムスタンプを用いる必要があります。日単位まで含めてバージョン名にしておけば大抵の場合は順序通りに並びます。
採用例
公式にHashVerを謳っている有名OSSはありませんが、CIを用いたナイトリービルドや社内ツールで類似の命名を採用している例はあります。例えばソフトウェアの nightly 版に2023-09-15-abcd1234
のようなバージョンを振ることがあります。HashVerはそうした実践を一般化したアイデアと言えるでしょう。
公式ドキュメント: HashVer仕様
GitDate
GitDateはHashVerに近い発想ですが、Gitのコミット日付に焦点を当てたバージョニング戦略です。コミットのハッシュでは人間には読みにくいという課題に対し、GitDateでは「いつコミットされたか」を軸にしています。
概要
SemVerでは解決できない問題に対処するため、Gitのコミット日時をバージョンに用います。これにより変更履歴を追いやすく、リリース間隔も明示されます。開発サイクルが速いプロジェクトで「このバージョンはいつのコミットまで入っているか」を明確にする目的で考案されました。
命名規則
YYYY.MM.DD.<git-short-hash>
の形式です。年/月/日を示した後に、その日のコミットを識別するGitの短いハッシュを付けます(例: 2021.03.22.d31d336
)。もう一つの例として2022.02.14.2c52a964
なら2022年2月14日のあるコミットという意味になります。バージョン名だけでリリース日が分かるのがメリットです。
自動バージョンアップ可能性: ✗
HashVerと同様、互換性情報は含まれません。例えば2021.03.22...
から2021.03.31...
に上がっていても、その間に破壊的変更があったかどうかはバージョン名からは判断できません。利点は「最終更新日」が分かる点なので、互換性は別途リリースノート等で確認する必要があります。
ソート可能性: △
日付を含んでいるため、基本的には日付順にソートすればリリース順になります。注意点は同じ日付に複数リリースがある場合で、短いハッシュ部分だけでは順序を保証できません。その際はGitのコミット時刻や履歴を参照して順序付けする必要がありますが、多くの場合1日1リリース程度であれば問題にならないでしょう。
採用例
提唱者のTaylor Brazelton氏が2022年に発表した概念上の方式で、広く一般には使われていません。ただし、CI/CDを活用する社内プロジェクトなどで内部的に類似のバージョン命名をしているケースはあります。また、GitDateの考え方は「ユーザーがそのソフトの最終更新日時をバージョン名から把握できる」という点でユニークで、顧客に常に最新版への更新を促すような製品で役立つかもしれません。
公式ドキュメント: Taylor Brazeltonブログ
PragVer(Pragmatic Versioning)
PragVer(プラグマティック バージョニング)は実用本位のバージョニング戦略です。ソフトウェアのリリース運用では「ユーザーに変更を知らせつつ、開発者側も管理しやすくしたい」というニーズがあります。PragVerはまさに開発者とユーザー双方にプラグマティック(実利的)な解を目指したものです。
概要
パッケージ利用者への変更内容の伝達と、開発者側の管理のしやすさを両立しようとする戦略です。SemVerのように厳密な互換性ルールで縛りすぎず、しかし利用者には何が変わったかを分かりやすく示します。2023年12月にSeverin Ibarluzea氏が提案しました。
命名規則
BIGRELEASE.ANNOUNCE.INCREMENT
の3要素で構成されます。
- BIGRELEASE:大きな節目のリリース番号です。プロジェクト側で任意に決めるブランド的な番号で、例えば年次の大型リリースやLTS期間開始を示す用途です。開発者の判断で計画的に上げる番号であり、ここが変わると利用者にも「大きな節目だ」と伝わります。
- ANNOUNCE:重要な変更やアナウンス事項があったときに上げる番号です。新機能追加や互換性に影響する変更など、ユーザーに注目してほしい変更を伴うリリースで増加します。SemVerでいうメジャー・マイナーに相当する重要度の変更に使われます。
- INCREMENT:細かな更新毎に上がる番号です。バグ修正や小さな改良などコントリビュージョン1件ごとにインクリメントされるイメージです。自動リリースフローと親和性があり、開発者が逐一リリースノートを書くほどでない変更でも番号が進みます。
自動バージョンアップ可能性: △
ANNOUNCEやBIGRELEASEが変わった際は重要な変更が入っていると分かるので慎重な対応が必要ですが、INCREMENTだけの増加であれば自動更新しても問題ないケースが多いでしょう。もっとも、PragVerは互換性よりも告知事項の明示を重視するので、セキュリティフィックス等もANNOUNCEを上げて通知する可能性があります。したがって機械的な安全判断にはあまり向かず、利用者への情報伝達が主目的と言えます。
ソート可能性: ✓
3つの数値が単調増加していくため、数値比較で順序付けできます。BIGRELEASEが上がれば大抵ANNOUNCEとINCREMENTはリセットされるでしょうし、ANNOUNCEが上がればINCREMENTがリセットされる想定です。そのため、例えば2.0.5
(Big2, Announce0, Incr5)より2.1.0
(Big2, Announce1, Incr0)の方が新しい、といった比較も通常のルールで可能です。
採用例
具体的な採用例はまだありません。Next.jsなどのフレームワークでSemVerの頻繁なメジャーアップが現場に混乱を招くケースなどを踏まえ、こうした提案が生まれています。今後、ある程度大規模なプロジェクトがPragVerを採用し、長期サポート版の区別や告知内容管理に活用するといった可能性はあるでしょう。
公式ドキュメント: pragmaticversioning.com
WendtVer
WendtVer(ヴェントバージョニング)は、Brian Wendt氏が提案した冗談混じりのバージョニング方式です。開発のたびに「次はメジャーを上げるべき?それともパッチ?」と悩むのが面倒になったことは多くの開発者にとって共感できる点でしょう。WendtVerは極端な話、「何も考えず常に決まった規則でカウントアップしよう」というアプローチです。
概要
開発者がバージョン番号を深く考えず機械的に増やすことを目的にした、半ば風刺的な戦略です。SemVerのように「この変更は重大か否か」と頭を悩ませる代わりに、とにかくコミットごとに番号を上げることで次のバージョンが予測しやすいようにしています。2018年に提案されました。
命名規則
MAJOR.MINOR.PATCH
の形式ですが、その増分ルールが独特です。初期バージョンは0.0.0とし、コミットするたびにPATCHを+1します。ただしPATCHが10になったら0に戻してMINORを+1、MINORが10になったら0に戻してMAJORを+1、というように各位が0〜9で繰り上がるカウンタになっています。結果、コミット履歴に沿って0.0.0 -> 0.0.1 -> ... -> 0.0.9 -> 0.1.0 -> ... -> 0.9.9 -> 1.0.0 -> ...と進みます。
自動バージョンアップ可能性: ✗
そもそも互換性を一切考慮しない戦略なので、バージョン番号からは何の情報も得られません。利用者にとってはただの通し番号です。アップデート時の注意点はバージョンでは判断できず、リリースノート頼りになります。
ソート可能性: ✓
数字としては単調増加していくため、通常の数値比較で並べ替えられます。ただし1.0.0の後に0.10.0のような異常系は起こらない前提(常に増え続ける)なので、順当に新しいものほど数値的にも大きくなります。WendtVerはバージョン番号に意味がないので、比較はシンプルです。
採用例
完全にジョークの域で、実際に採用しているOSSは無いと思われます。極端ですが「バージョン番号なんて飾り」というメッセージでもあり、SemVer至上主義への皮肉として語られることが多いです。もし採用すれば毎日何らかの変更をコミットするような超アジャイル開発で威力を発揮する…かもしれません。
公式ドキュメント: wendtver.org
SoloVer
SoloVer(ソロバージョニング)は単一の番号でバージョン管理を行う戦略です。多くの方式がドットで区切った複数の数字を使いますが、SoloVerは思い切って1つにしてしまおうという大胆な提案です。「バージョン1、2、3…でいいんじゃないか」と思うことがある開発者も多いでしょう。それを正式にルール化した感じですね。
概要
シンプルさと表現力を重視した戦略です。余計な情報はバージョン番号に載せず、互換性などは別途ドキュメントで示すべきという割り切りがあります。バージョン番号自体はただのリリースの通し番号と捉え、誰にでも分かりやすいようにしました。2024年3月にbeza1e1氏によって提案されています。
命名規則
<番号>[<ポストフィックス>]
という形式です。基本は単一の整数で、初期バージョンを0としてリリースごとに1ずつ増やします。オプションでポストフィックスを付けることができ、+
または-
で始まる英数字列という規則になっています。-
はプレリリース(ベータ版など)、+
は緊急のホットフィックスのように使い分ける想定です。
自動バージョンアップ可能性: ✗
番号自体に互換性の情報は一切含まれません。極端な話、1から2に上がった変更が致命的な破壊的変更かもしれませんし、10から11への変更が些細な修正かもしれません。バージョン番号は単なるリリース順序なので、自動更新の可否は開発元のアナウンスを見る必要があります。
ソート可能性: ✓
ただの整数ですので、数値の大小で簡単に並べ替え可能です。ポストフィックスもソート規則が定められており、基本の番号が同じ場合は-
(プレリリース)が最も低く、何も付かない正式版がその次、+
(後付けの修正)がその後になるよう定義されています。この規則に従えば、例えば「2-beta」<「2」<「2+hotfix」という順序になります。
採用例
提唱されたばかりであり、広く使われている例はありません。しかし一部の小規模ライブラリや内部プロジェクトで「とにかくリリース番号を増やすだけ」という運用が行われていることはあります。SoloVerはそれを明文化したもので、シンプルさを重視する開発者には魅力的かもしれません。
公式ドキュメント: SoloVer仕様
BreakVer(Break Versioning)
BreakVer(ブレイク バージョニング)は、SemVerの課題を解決しようとして生まれた戦略です。SemVerでは「どの程度の破壊的変更か」に関係なくメジャーを上げるしかありませんが、BreakVerは破壊的変更の大きさを細かく表現しようとしています。「小さな非互換変更なのにメジャーを上げるべきか」というジレンマに答えるものです。
概要
SemVerの仕様(特に0.xやプレリリース扱いの複雑さ)を簡素化しつつ、メジャーとマイナーの両方で破壊的変更を表現できるようにした戦略です。SemVerでは互換性が壊れる変更はすべてメジャーでしか表現できませんでしたが、BreakVerでは「大きな破壊」か「小さな破壊」かを区別します。2015年にPeter Taoussanis氏がClojure向けライブラリencoreの中で提唱しました。
命名規則
<major>.<minor>.<non-breaking>[-<qualifier>]
の形式です。4つ目の要素(プレリリースやビルドメタデータ)はオプションです。各部分の意味は次の通り:
- major:重大な破壊的変更、または非常に大きな機能追加があった場合に上げる番号。
- minor:小規模な破壊的変更や重要ではない破壊なしの変更があった場合に上げる番号。
- non-breaking:破壊的変更なしの場合に上げる番号(バグ修正や軽微な追加のみ)。
- qualifier:任意の補足タグ。
-alpha1
や-RC2
のようにプレリリース段階を示すのに使います。
自動バージョンアップ可能性: ✓
各バージョン部分が最大の影響度を表すため、non-breaking部分の増加であれば常に後方互換で安全な更新と分かります。minorが増えた場合は「小さな破壊的変更があるかもしれないのでChangelogを確認して」との合図になり、majorが増えた場合は「重大な破壊あり、注意してアップグレードを」と明示されます。このように、安全度の指標が細かく提示されるので、自動アップデート可否の判断材料になります。ただし実際には「minorの破壊」がどの程度かは開発者の判断に依存するため、利用者側も注意は必要です。
ソート可能性: ✓
数値3つの構成で、基本的にはSemVer同様に数値順で並べ替え可能です。注意点として、qualifier付きのもの(プレリリース版)は正式版より下位とするなどのルールが必要ですが、これもSemVerに倣えば問題ありません。破壊度合いが違っても、バージョン番号自体は単調増加してゆくことが期待されます。
採用例
Clojure界隈で提唱され、実際にTaoussanis氏のライブラリEncoreで採用されています。しかし広く一般には浸透していません。SemVerほど厳密でなくとも良いが、互換性に敏感な場面でうまく運用できれば有用でしょう。例えば、社内ライブラリで「設定ファイルの後方互換が一部壊れたが機能は大半影響なし」というときにminorを上げるといった使い方が想定されます。
公式ドキュメント: Taoensso: BreakVer
Explicit Versioning
Explicit Versioning(エクスプリシット バージョニング)は、その名の通り意図的な非互換変更を明示的に扱う戦略です。SemVerではメジャー番号が上がったときに破壊的変更があったと推測しますが、Explicit Versioningではさらに一歩踏み込み、「破壊的変更を起こすぞ」という宣言をバージョンに織り込みます。
概要
開発者がリリース時に明確に破壊的変更を宣言したい場合に有用な戦略です。バージョン番号にその意思を埋め込むことで、利用者に対して「ここに注意してほしい」というメッセージを送ります。2017年にPaulo Renato氏によって提唱されました。
命名規則
Disruptive.Incompatible.Compatible.Fix
という4つのセグメントからなるバージョンです。それぞれの意味は次の通りです。
- Disruptive:破滅的変更があった場合に上げる一番左の番号です。通常の非互換変更(後述のIncompatible)よりさらに大きな「システム全体に影響する事態」などに使います。例えば大規模なプラットフォーム移行や、プロジェクトの大転換期などです。
- Incompatible:後方非互換の変更で上げる番号です。SemVerのメジャーに相当しますが、上記Disruptiveほどではない意図的な非互換(通常のメジャー変更)があればここを増やします。
- Compatible:後方互換な変更(機能追加など)で上げる番号です。SemVerのマイナーに相当し、既存ユーザーに影響のない範囲でのアップデート時に増やします。
- Fix:バグ修正など極小の変更で上げる番号です。SemVerのパッチに相当します。
- Optional:必要に応じて
-beta
や+build
のような付加情報を付けられます。
自動バージョンアップ可能性: ✓
SemVer以上に明確に互換性レベルが区別されています。特にDisruptiveは通常起こらない大事件用なので、普通の非互換はIncompatibleで表現されます。このため、例えばCompatibleやFixが上がったバージョンならば安心して自動アップデートしてよいでしょう。一方、Incompatibleが上がった場合は破壊的変更があると明言されているので注意が必要です。Explicit Versioningに従っていれば、開発者が意図的に互換性を切った箇所が明確になるため、ユーザーも対応を計画立てやすくなります。
ソート可能性: ✓
4つの番号すべて数値なので、通常の数値比較で並べ替え可能です。セグメントが一つ増えていますが、例えば1.0.0.0から1.1.0.0、1.1.1.0、...1.1.1.5のように、左から順に比較すれば順序が一意に決まります。従来の3桁より多少ルールは複雑になりますが、プログラムで処理する分には問題ありません。
採用例
提案段階の概念であり、広く採用された事例は確認できません。SemVerを拡張する形なので理解はしやすいですが、運用コストが上がることから敬遠されているようです。ただ、APIレベルで厳密な互換管理が必要なプロジェクトや、長期運用で破壊的変更を段階的に実施するような場合には有用かもしれません。現時点では議論やRFCレベルに留まっています。
公式ドキュメント: Explicit Versioning (GitHub)
ZenVer(Zen Versioning)
ZenVer(禅バージョニング)は、一言でいえば「バージョン番号について無心になる」戦略です。提唱文には「大きい数字はより新しい。数字が大きいほどソフトウェアは良くなる」とあります。要するに、ひたすら番号を上げ続けるのです。初めてZenVerを見ると思わず笑ってしまうかもしれませんが、考えてみればバージョン番号とはそういうものかもしれません。
概要
従来のどの方式よりも単純明快な戦略です。開発者に要求されることは何もなく、ただ「前より新しければ数字を大きくする」だけです。セマンティックな意味付けを一切排除し、バージョン番号=更新順という本質に立ち返っています。
命名規則
VERSION
という単一の数値を使用します。厳密には1つの整数を使う点でSoloVerに近いですが、ZenVerの場合その数値が何を意味するかについて一切語りません。ただルールとして「非互換な変更をしてもVERSIONを上げる、機能追加でも上げる、バグ修正でも上げる、何か変更したらとにかく上げる」と繰り返し述べています。要するにどんな変更でもバージョン番号を+1するだけです。
自動バージョンアップ可能性: ✗
互換性は全く読み取れません。数字が1上がっただけでは、それが破壊的変更かどうか分からないからです。ZenVerは互換性情報を捨て去った代償に単純さを得ているため、利用者は必ず変更内容を自分で確認する必要があります。
ソート可能性: ✓
数字はただ単調増加していくだけなので、比較・ソートは極めて簡単です。「5より6が新しい」という普通の判断だけでOKです。内部的にはSoloVerと同様ですが、ZenVerの場合プレリリースやビルドメタデータすら許容しない(Zenの境地では余計な付加は排する)点が特徴です。
採用例
2024年提案のジョーク的戦略であり、広く採用された例はありません。しかし振り返ると、例えばGoogle Chromeのバージョンなどは毎回メジャー番号を上げ続けています。あれはZenVerに近い運用とも言えるでしょう。公式にはZenVerという名前は使われていませんが、「とにかく番号だけ上げる」という割り切りは意外と身近な所に存在しています。
公式ドキュメント: ZenVer仕様 (GitHub)
PVP(Package Versioning Policy)
PVP(パッケージ バージョニング ポリシー)はHaskellコミュニティで用いられている厳格なルールのバージョニング指針です。SemVerの登場(2010年)より以前の2006年に策定されており、Haskellのパッケージ依存関係管理に最適化されています。Haskellを触った際にこの存在を知ると、コミュニティごとに独自の文化があるのだと感心させられます。
概要
Haskellにおけるライブラリ開発者と利用者が、互換性の破綻しない範囲でバージョンを指定・管理できるよう定められたポリシーです。ライブラリ作者はこの規約に従ってバージョン上げを行い、利用者(他の開発者)は依存バージョンの範囲指定をPVPに従って記述します。結果、ビルドが壊れる依存組み合わせを極力避けるようになっています。
命名規則
基本の形式はA.B.C
(必要に応じてさらにドット区切りの追加要素を持ってもよい)です。PVPではA.Bをメジャーバージョン、Cをマイナーバージョンと呼びます。バージョン上げのルールは以下の通りです:
- 破壊的変更があった場合:新しいA.Bは前のリリースより大きくならなければいけません(メジャーバージョンアップ)。関数や型の削除、互換性のなくなる型定義変更などが該当します。
- 非破壊的な機能追加があった場合:A.Bは据え置きで、新しいCを前より大きくします(マイナーバージョンアップ)。既存APIを壊さず関数やモジュールを追加する変更がこれに当たります。
- その他細かな変更(ドキュメント修正や依存関係範囲の変更のみ等)の場合:A.B.Cはそのままでも構いません(4つ目以降の要素を持つ場合はそれを増やしてもよい)。
要はSemVerと似ていますが、2段階のメジャーバージョン(A.B)を持つ点が特徴です。例えば1.5.*から1.6.*へのアップは破壊的変更、1.5.3から1.5.4は非破壊的追加、といった具合です。
自動バージョンアップ可能性: ✓
破壊的変更か否かがバージョンに明確に反映されています。特にHaskellでは依存ライブラリの許容バージョン範囲を指定する際、上限は次の非互換版未満(例えば< 1.6
のように)とするのが一般的です。これはPVPに則り、1.6になったら破壊的変更が入るはずだから避ける、という発想です。逆に言えば1.5.xの範囲であれば後方互換が保たれると信頼できるため、自動更新してもビルドが壊れないことが保証されます。
ソート可能性: ✓
ドット区切りの数値列を辞書式に比較するルールが定義されています。例えば2.0.1 > 1.3.2、2.0.1.0 > 2.0.1 といった順序です。基本的には数値部分を左から比較するSemVerと同じ考え方で、要素数が異なる場合は追加要素がある方が新しい(2.0.1.0は2.0.1より新しい)とみなします。
採用例
主にHaskellのパッケージ(Cabal/Hackage)で採用されています。HaskellコミュニティではSemVerではなくこのPVPに従うのが一般的で、StackやCabalといったビルドツールもPVPを念頭において依存解決を行います。SemVerとの違いとして、0.x.yバージョンにも特別な意味を設けていない点や、4桁以上のバージョン番号も許容している点があります。
公式ドキュメント: PVP (Haskell)
FloatVer
FloatVer(フロート バージョニング)は一風変わった戦略で、浮動小数点数によってバージョンを表現します。ソフトウェアのバージョンに小数を使う例(ブラウザの1.5とか2.0とか)は昔からありますが、FloatVerはそれを徹底してIEEE754単精度浮動小数として扱おうという提案です。
概要
数値としてネイティブに扱えるバージョンを目指した戦略です。32ビット浮動小数点数は多くの言語・CPUでサポートされており、その比較はハードウェアでも高速です。FloatVerではバージョン番号をそのまま浮動小数として比較・演算できる利点を強調しています。
命名規則
基本形式はbreaking.nonbreaking
で、小数点で区切った2桁の数字列に見えますが、実体は単一の浮動小数です。例えばバージョン0.7や290.10008といった例が挙げられています。解釈としては、小数点前を破壊的変更のカウント、小数点後を非破壊的変更のカウントとみなします。具体的なルールは次の通りです:
- 互換性のない変更をした場合、breaking(整数部)を+1します。このとき非破壊部分(小数部)は任意の値に変更して構いません。
- 後方互換な変更をした場合、nonbreaking(小数部)を増やします。整数部は変更しません。なお、非破壊変更では整数部(breaking)を変更してはいけないというルールです。
- 0.0から開始し、以降は常に数値が上がっていくようにします。浮動小数の特性上、0.0が最小のバージョン、最大は約3.4028235e38(単精度浮動小数の最大値)です。
自動バージョンアップ可能性: ✗
非破壊的変更のみであれば小数部分が増えるだけなので、互換性が保たれていると判断できます。FloatVerでは「非破壊(互換)変更」の定義も厳密に示されており、機能の振る舞いが変わらずリソース消費も許容範囲内であることなどを条件としています。これらを満たす限り小数部分の増分は安全なアップデートと見なせ、ツールによる自動バージョンアップも可能でしょう。ただし、この保証を運用で守るのは難しい側面もあります。
ソート可能性: ✓
浮動小数点数同士の比較で大小関係を判定できます。0.7 < 1.0 < 1.5 < 2.0 といった具合で、人間にとっても直感的ですし、コンピュータにとっても単純な数値比較になるため効率的です。ただし浮動小数特有の丸め誤差に注意が必要ですが、提案ではIEEE754に完全準拠する実装を想定しているようです。
採用例
2024年7月にAlex Shroyer氏が提案した新しい方式で、まだ採用例は見当たりません。アイデアとして面白いものの、「浮動小数を使う必然性は?」という声もあり、議論段階のネタ的な要素が強い印象です。実運用するには各種ビルドツールや言語のバージョン比較が対応していないと難しいでしょう。ただ、バージョンを一つの可算値として扱う発想は、将来的に何らかの形で応用されるかもしれません。
公式ドキュメント: Alex Shroyerの提案
AsymptoVer
AsymptoVer(アシンプトバージョニング)はちょっと学術的なユーモアが効いた戦略です。バージョン番号がある極限値に次第に近づいていくというユニークなコンセプトで、ドナルド・クヌース氏によって有名になりました。例えば、ソフトウェアの完成度が100%に漸近するイメージでバージョンを付けるようなものです。
概要
無限小数に漸近するようなバージョン付けを行います。具体的には、ある数学的な定数(無理数など)の値にバージョン番号が近づいていくようリリースごとに桁を増やしていきます。バージョン番号がどんどん長くなり、理論上は無限にリリースを重ねても極限値に到達しないという遊び心があります。
命名規則
明確な一般式はありませんが、有名な例としてTeXとMetafontがあります。
- TeXはバージョン番号が3に漸近するようになっており、3, 3.1, 3.14, 3.141, ...と円周率$\pi$の小数展開に沿って追加されています(最終的に3.14159265まで出ています)。
- Metafontはバージョン番号が2に漸近し、2, 2.7, 2.71, 2.718, ...とネイピア数$e$に近づくよう付けられています。
他にもジョークとして無理数や超越数なら何でも利用可能だと言われています。
自動バージョンアップ可能性: ✓
基本的にはい。TeXは3.0で設計を凍結し、以降の3.xxxxx版はバグ修正のみで後方互換を保つという方針をとっています。つまり漸近的に上がる間、基本的に互換性は維持されています。互換性というよりバージョン体系そのものがジョークなので、一般的な依存管理には適しませんが、意図としては「大きな変更はもうない」という宣言でもあります。
ソート可能性: ✓
漸近とはいえ数値は単調増加します(πやeは増加列ではありませんが、付与桁数が増えるごとに数値は大きくなります)。そのため通常の数値比較で新旧を判定可能です。
採用例
Donald Knuth氏のTeXとMETAFONTが有名な実例です。TeXは3.14159265までバージョンが上がっており、METAFONTは2.7182818が最新版です。Knuth氏の著作物に限定された特例的戦略ですが、そのユニークさからしばしば話題になります。
公式ドキュメント: TeXの版番号 (Wikipedia)
TrunkVer
TrunkVer(トランクバージョニング)は、継続的デリバリー(CI/CD)環境に適した自動バージョニング戦略です。Trunk-based development(常にメインブランチで開発し続ける手法)で頻繁にビルド・デプロイする場合、人手でバージョンを管理するのは大変です。CI/CDパイプラインで「あれ、次のバージョン何番だっけ?」となることがある開発者も多いでしょう。TrunkVerはそれを自動化します。
概要
ビルドのたびにタイムスタンプやコミットIDを埋め込んだバージョンを生成する仕組みです。SemVerと互換性のあるフォーマットを採用しつつ、手動のバージョン議論を無くすことを目指しています。2024年5月にChris Klyk氏とRaimo Radczewski氏らによって提唱されました。
命名規則
YYYYMMDDHHMMSS.0.0-g<COMMIT_HASH>-<BUILD_REF>
という形式を提案しています。具体的には:
- タイムスタンプ:
YYYYMMDDHHMMSS
部分がUTC日時(年月日時分秒)を表します。これをバージョン番号の最初の部分(いわゆるMAJORに相当)に据えています。 - 固定の0.0:タイムスタンプの後に
.0.0
と続きます。これはSemVer形式を満たすためのダミーのMINOR.PATCHです。常に0.0とすることで、タイムスタンプだけが実質的なバージョンの差異を表すようにしています。 - コミットハッシュ:
g<COMMIT_HASH>
としてGitの短いコミットハッシュを埋め込みます。バージョンからどのソース時点かが追跡できます。 - ビルド参照:
-<BUILD_REF>
としてCIパイプラインのビルド番号やブランチ名などを入れます。例えばGitLabのパイプラインIDや手動ビルドの識別子を入れて、ビルドを一意に識別します。
自動バージョンアップ可能性: ✗
はい(常に自動生成)。TrunkVerでは人間がバージョンを増やす作業自体ありません。CI/CDがバージョンを自動付与します。そのため互換性の概念はバージョン名に含まれず、利用者も常に最新への更新を前提とする運用になります。古いバージョンとの互換性懸念は別途コミュニケーションする必要がありますが、継続的デプロイを前提とした環境では常に順次アップデートしていく想定でしょう。
ソート可能性: ✓
タイムスタンプが秒精度まで含まれているため、文字列比較でも時間順に並べられます(YYYYMMDDHHMMSSの文字列は辞書順=時系列順になります)。一日に複数ビルドしても時分秒まで入っていれば問題ありません。コミットハッシュとビルド番号は主に識別用で、ソートには影響しない位置付けです。
採用例
提唱元であるcrafted-tech社の内部ツールなどで試用されているようですが、一般的なOSSでの採用例はまだありません。しかしCI/CDをフル活用するプロジェクトでは魅力的な方式です。例えばマイクロサービスで日次デプロイするようなケースでは、TrunkVerで自動生成されたバージョンを付けておけば、いつデプロイしたものか一目で分かり監査やトラブルシュートに役立ちます。SemVerとの互換性もあるため、既存のパッケージシステムに載せる際も受け入れられやすいでしょう。
公式ドキュメント: trunkver.org
おわりに
以上、18種類のバージョニング戦略を紹介しました。各戦略にはそれぞれの特徴と利点があり、プロジェクトの性質や開発スタイルに応じて最適な方式を選ぶことが重要です。
主流のSemVerは互換性を明示でき自動更新の判断基準になる点で優れています。定期的なリリースを行うプロジェクトではCalVerが分かりやすいでしょう。CI/CD環境ではTrunkVerのようなタイムスタンプベースの自動生成も便利です。
また、独自性を出したい場合はRomVerや、極端なケースではSentimental Versioningのような「作者の感性」を重視する方式もあります。TeXのような名作は数学定数に漸近するAsymptoVerという遊び心までありました。
最終的には、開発チームと利用者のコミュニケーションをスムーズにするという目的を忘れなけいことが大事だと思います。