# Семантическое версионирование

> Соглашение о номерах версий MAJOR.MINOR.PATCH, в котором каждая цифра сообщает о характере изменений — несовместимых, новых возможностях или исправлениях.

Источник: https://llmdocs.ru/wiki/semver/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **Автор**: Том Престон-Вернер
- **Текущая версия спецификации**: 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](https://llmdocs.ru/wiki/github.md), обобщив сложившуюся практику открытых проектов. Версия 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](https://llmdocs.ru/wiki/python.md) использует собственную схему 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](https://llmdocs.ru/wiki/github-actions.md) или другой CI-системы.

```text
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`, pip `25.1`, JetBrains `2025.2` — номер говорит о дате, а не о совместимости.[6]

Несмотря на это, SemVer остаётся общим языком между авторами библиотек и их пользователями, и его соблюдение — признак зрелого проекта.

## См. также

- [Git](https://llmdocs.ru/wiki/git.md)
- [pip и PyPI](https://llmdocs.ru/wiki/pip-pypi.md)
- [Cargo](https://llmdocs.ru/wiki/cargo.md)
- [Helm](https://llmdocs.ru/wiki/helm.md)

## Источники

1. [Semantic Versioning 2.0.0](https://semver.org/)
2. [npm Docs — About semantic versioning](https://docs.npmjs.com/about-semantic-versioning)
3. [Cargo Book — SemVer Compatibility](https://doc.rust-lang.org/cargo/reference/semver.html)
4. [Go Modules Reference — Major version suffixes](https://go.dev/ref/mod#major-version-suffixes)
5. [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/)
6. [Calendar Versioning](https://calver.org/)
7. [PEP 440 — Version Identification and Dependency Specification](https://peps.python.org/pep-0440/)
