Семантическое версионирование
| Автор | Том Престон-Вернер |
|---|---|
| Текущая версия спецификации | 2.0.0 (2013) |
| Формат | MAJOR.MINOR.PATCH[-предрелиз][+сборка] |
| Лицензия спецификации | CC BY 3.0 |
| Используется | npm, Cargo, Go-модули, Helm, многие библиотеки |
| Альтернативы | календарное версионирование (CalVer), PEP 440 в Python |
| Сайт | semver.org |
Семантическое версионирование (англ. Semantic Versioning, SemVer) — соглашение о том, как присваивать номера версиям программ, чтобы номер сам говорил о характере изменений. Версия записывается как MAJOR.MINOR.PATCH, например 2.7.1: рост первой цифры означает несовместимые изменения, второй — новые возможности без поломок, третьей — только исправления ошибок.[1] Благодаря этому пакетные менеджеры могут автоматически обновлять зависимости в безопасных пределах, а пользователь библиотеки заранее знает, чего ждать от обновления.
История
Спецификацию написал Том Престон-Вернер, сооснователь GitHub, обобщив сложившуюся практику открытых проектов. Версия 2.0.0, действующая до сих пор, опубликована в 2013 году на сайте semver.org. Соглашение было принято экосистемами npm, Cargo, Go-модулей, Composer, Helm и многими другими.
Правила
Обязательное условие — у проекта есть публичный API: документированный интерфейс, относительно которого и определяется совместимость. Дальше:[1]
| Что изменилось | Какую часть увеличить | Пример |
|---|---|---|
| Несовместимое изменение API | MAJOR, остальные обнуляются | 1.4.2 → 2.0.0 |
| Новая возможность, обратно совместимая | MINOR, PATCH обнуляется | 1.4.2 → 1.5.0 |
| Исправление ошибки без изменения API | PATCH | 1.4.2 → 1.4.3 |
Ещё несколько важных пунктов:
- Опубликованная версия неизменна: исправление выпускается новым номером, а не перезаписью старого.
- Версии
0.y.z— начальная разработка: API нестабилен, и ломать его можно в любой момент. Версия1.0.0объявляет публичный API стабильным. - Предрелизы записываются через дефис:
2.0.0-alpha,2.0.0-beta.2,2.0.0-rc.1. Они младше соответствующего релиза:2.0.0-rc.1 < 2.0.0. - Метаданные сборки — через плюс:
1.0.0+20261109.sha.5114f85. При сравнении версий они игнорируются. - Сравнение покомпонентное и числовое:
1.10.0 > 1.9.0, а предрелизные метки сравниваются по частям —alpha.2 < alpha.10 < beta.
Диапазоны версий
Пакетные менеджеры используют SemVer, чтобы описывать допустимые обновления:[2]
| Запись (npm) | Разрешает | Смысл |
|---|---|---|
^1.4.2 |
>=1.4.2 <2.0.0 |
любые совместимые обновления |
~1.4.2 |
>=1.4.2 <1.5.0 |
только исправления |
1.4.2 |
ровно эту версию | полная фиксация |
^0.4.2 |
>=0.4.2 <0.5.0 |
в нулевой версии MINOR считается «мажорным» |
В Cargo запись "1.4.2" по умолчанию означает то же, что ^1.4.2.[3] В Go несовместимая версия модуля получает новый путь импорта с суффиксом: example.com/lib/v2 — так две мажорные версии могут жить в одной программе.[4] Python использует собственную схему PEP 440, которая совместима с SemVer по форме, но допускает и другие варианты (1.0.post1, 2.0rc1); оператор ~= в ней похож на тильду npm.[7]
Диапазоны дают гибкость, но для воспроизводимых сборок точные версии фиксируются в lock-файлах (package-lock.json, Cargo.lock, uv.lock), которые хранят в репозитории.
Автоматизация
Соглашение Conventional Commits структурирует сообщения коммитов: fix: соответствует PATCH, feat: — MINOR, а BREAKING CHANGE: в теле или ! после типа (feat!:) — MAJOR.[5] Инструменты semantic-release, release-please и changesets по истории коммитов сами вычисляют следующую версию, пишут журнал изменений и публикуют релиз из GitHub Actions или другой CI-системы.
feat(api): добавить фильтр по дате → 1.5.0
fix: не падать на пустом ответе → 1.5.1
feat!: удалить устаревший метод /v1/list → 2.0.0
Номер версии обычно ставят и Git-тегом: git tag -a v1.5.1 -m "Release 1.5.1".
Ограничения и критика
- Совместимость — суждение человека. Изменение поведения, исправление ошибки, на которую кто-то полагался, или поднятие минимальной версии языка формально могут оказаться «ломающими». Отсюда шутка, что любое изменение для кого-то мажорное.
- «Вечный ноль». Многие популярные проекты годами живут в
0.x, обходя обязательства SemVer. - Неприменимость к продуктам без API. Для приложений и операционных систем часто удобнее календарное версионирование (CalVer): Ubuntu
24.04, pip25.1, JetBrains2025.2— номер говорит о дате, а не о совместимости.[6]
Несмотря на это, SemVer остаётся общим языком между авторами библиотек и их пользователями, и его соблюдение — признак зрелого проекта.