Управление версиями в разработке: SemVer, Conventional Commits и другие подходы

Когда разработчик видит номер версии вроде "2.3.7", он подсознательно ожидает определённое поведение от обновления. Он предполагает, что обновление безопасно, что код не сломается и что изменения будут ограниченными. Именно для этого и существует версионирование.

Версионирование - это способ заранее предупредить других людей о последствиях обновления. Если версии присваиваются без правил, цифры теряют смысл, а обновления становятся лотереей.


Зачем версионирование нужно на практике

Рассмотрим несколько типичных ситуаций.

Ситуация 1. Обновление библиотеки

Проект использует библиотеку версии 1.4.2. Вы обновляете её до 1.4.3 и ожидаете:

  • только исправления ошибок

  • отсутствие изменений в API

  • стабильную работу

Если же после такого обновления код ломается, значит правила версионирования не соблюдаются.

Ситуация 2. Большой релиз продукта

Вы видите релиз 3.0.0 и понимаете:

  • появились серьёзные изменения

  • возможно, придётся адаптировать код

  • нужно читать описание релиза

Номер версии уже сообщает важную информацию, ещё до прочтения changelog.


Основные подходы к версионированию

Простая нумерация

v1
v2
v3

Такой подход ничего не говорит о характере изменений. Версия v10 может отличаться от v9 одной строкой кода, а может быть полностью переписанной.

Версионирование по дате

2024.11
2025.02

Хорошо подходит для продуктов с регулярными релизами. Например, операционные системы или SaaS-сервисы. Но здесь тоже нет информации о совместимости.

Semantic Versioning

Semantic Versioning вводит чёткий формат, который помогает понять какой тип изменений ожидать в обновлении:

MAJOR.MINOR.PATCH

Далее рассмотрим Semantic Versioning подробнее.


Semantic Versioning (SemVer)

Стандарт, который описывает не просто номер версии, а смысл изменений. Он показывает, безопасно ли обновляться и чего ожидать от релиза. Именно этот подход чаще всего используется в библиотеках, фреймворках и API.

Рассмотрим каждую часть подробнее:

PATCH: исправления без последствий

PATCH увеличивается, когда исправляются ошибки и ничего не ломается.

Примеры изменений:

  • исправлен баг в расчёте скидки

  • устранена утечка памяти

  • поправлена валидация формы

Пример версий:

1.0.0 → 1.0.1
1.2.5 → 1.2.6

Пример коммита:

fix(cart): исправлен расчёт итоговой суммы

Пользователь может обновляться без опасений.

MINOR: новые возможности без ломки

MINOR увеличивается, когда добавляется функциональность, но старый код продолжает работать.

Примеры изменений:

  • добавлен новый API-метод

  • добавлена настройка, но старая логика сохранена

  • расширен ответ API новыми полями

Пример:

1.3.0 → 1.4.0

Пример коммитов:

feat(profile): добавить аватар пользователя
feat(api): вернуть поле "created_at" в ответе

Важно: если старый код не ломается, это не MAJOR-изменение.

MAJOR: ломающие изменения

MAJOR увеличивается, когда изменения могут сломать существующий код.

Типичные причины:

  • удалён метод или эндпоинт

  • изменён формат ответа API

  • изменено поведение функции

  • обязательные параметры изменены

Пример:

1.9.2 → 2.0.0

Пример коммита:

feat(api): изменить формат ответа пользователя

BREAKING CHANGE: поле "name" заменено на "full_name"

Или короткий вариант:

feat!: изменить контракт API пользователя

Это прямой сигнал о необходимости обновления интеграций.


Что такое пре-релизы на практике

Пре-релизы - это промежуточные версии между текущей стабильной версией и будущим полноценным релизом. Они используются, когда изменения уже готовы, но ещё не считаются полностью стабильными.

В SemVer такие версии обозначаются дополнительным суффиксом:

2.0.0-alpha
2.0.0-beta
2.0.0-rc.1

Примеры использования:

  • alpha - ранняя версия для команды

  • beta - версия для тестирования пользователями

  • rc - кандидат в релиз

Такие версии помогают найти ошибки до стабильного релиза.

Также, важно понимать, что любые пре-релизы считаются нестабильными и по умолчанию не предназначены для продакшена.


Conventional Commits с примерами

Conventional Commits - это способ писать коммиты так, чтобы их понимали и люди, и инструменты.

Формат:

type(scope): описание

Примеры хороших коммитов

fix(auth): исправлена ошибка обновления токена
feat(search): добавить поиск по тегам
docs(readme): обновить инструкцию запуска
refactor(order): упростить логику расчёта
chore(ci): обновить pipeline сборки

По одному коммиту уже понятно, что произошло.

Примеры плохих коммитов

update
fix
changes
work

Такие сообщения не несут информации и бесполезны для истории проекта.

Breaking changes в Conventional Commits

Изменения, которые могут поломать код, всегда должны быть явно обозначены.

Пример:

feat(auth): изменить механизм авторизации

BREAKING CHANGE: токены старого формата больше не поддерживаются

Или:

feat!: удалить устаревший метод логина

Это позволяет автоматически увеличить MAJOR-версию.


Связь между коммитами и версиями

На практике работает простое правило:

  • fix → PATCH

  • feat → MINOR

  • feat! или BREAKING CHANGE → MAJOR

Пример истории коммитов:

fix(ui): исправить отображение кнопки
feat(profile): добавить редактирование профиля

Следующая версия:

1.2.3 → 1.3.0

Если появляется breaking change:

feat!: изменить формат настроек

Версия становится:

2.0.0

Changelog на основе коммитов

Хороший changelog может выглядеть так:

## 2.1.0
- Добавлена фильтрация заказов
- Улучшена производительность поиска

## 2.0.0
- Изменён формат API заказов
- Удалена устаревшая логика авторизации

## 1.9.4
- Исправлена ошибка расчёта доставки

Он формируется автоматически из истории коммитов.


Когда всё это действительно нужно

SemVer и Conventional Commits особенно полезны, если:

  • проект развивается долго

  • над кодом работает команда

  • есть внешние пользователи или API

  • используется CI/CD

  • важно поддерживать обратную совместимость

Для MVP или прототипа можно начать проще и внедрять правила постепенно. Они придадут проекту порядок и прозрачность.

Комментарии (0)

Войдите, чтобы оставить комментарий

Похожие статьи

Как создать AI-агента на Python с OpenAI для автоматического парсинга счетов

Подробный гайд, как разработать полноценного AI-агента на Python и OpenAI API, который автоматически парсит счета (PDF, фото), вытягивает данные в структурированный JSON, валидирует их и сохраняет в CSV или базу. Плюс интеграция с Telegram-ботом для загрузки документов.

46 0 3 мин

NativePHP для мобильных приложений стал полностью бесплатным

NativePHP for Mobile с версии v3 стал полностью бесплатным и открытым, с переходом на плагинную архитектуру, новым инструментом Jump для тестирования и другими нововведениями для разработчиков на Laravel.

23 0 1 мин