Версионирование и Epoch
Как rpm сравнивает версии и когда нужен Epoch.
На этой странице
Правильное версионирование гарантирует, что dnf upgrade обновит пакет корректно. Ошибки в версионировании — одни из самых сложных в исправлении.
Как RPM сравнивает версии
Полная версия пакета — это Epoch:Version-Release (EVR).
Приоритет сравнения:
- Epoch (наивысший приоритет)
- Version
- Release
# Проверить порядок версий
rpmdev-vercmp 1.0-1 1.1-1
# 1.0-1 < 1.1-1
rpmdev-vercmp 1:1.0-1 2.0-1
# 1:1.0-1 > 2.0-1 (Epoch 1 больше неявного Epoch 0)
Алгоритм сравнения Version
RPM разбивает строку версии на сегменты и сравнивает их:
1.12.3 → [1] [12] [3]
1.9.10 → [1] [9] [10]
1 == 1
12 > 9 → 1.12.3 > 1.9.10 (числовое сравнение!)
Числовые сегменты сравниваются как числа, строковые — лексикографически:
1.0a < 1.0b (строковое: 'a' < 'b')
1.0.1 > 1.0 (больше сегментов)
1.0 == 1.0.0 (хвостовые нули игнорируются)
Release: версия упаковки
Version: 2.1.0
Release: 1%{?dist}
Правила:
- При обновлении Version — сбрасывайте Release в
1 - При изменении только SPEC (патч, зависимость) — увеличивайте Release
2.1.0-1.rosa13.1 ← Первая сборка версии 2.1.0
2.1.0-2.rosa13.1 ← Исправлен SPEC (добавлен патч)
2.1.0-3.rosa13.1 ← Ещё одно исправление
2.2.0-1.rosa13.1 ← Новая версия upstream
Предрелизные версии (alpha, beta, rc)
Проблема
Upstream выпускает 2.0-rc1, потом 2.0. Но RPM считает:
2.0.rc1 > 2.0 ← НЕПРАВИЛЬНЫЙ порядок!
Решение: тильда (~)
Тильда делает версию ниже финальной:
# Release Candidate — ниже 2.0
Version: 2.0~rc1
Release: 1%{?dist}
# Финальный релиз
Version: 2.0
Release: 1%{?dist}
Проверка:
rpmdev-vercmp 2.0~rc1-1 2.0-1
# 2.0~rc1-1 < 2.0-1 ✓
Правильный порядок:
2.0~alpha1 < 2.0~beta1 < 2.0~rc1 < 2.0 < 2.0.1
Каретка (^) — пост-релизные снапшоты
Каретка делает версию выше текущей, но ниже следующей:
# Снапшот после 2.0, но до 2.0.1
Version: 2.0^20250203gitabc1234
Release: 1%{?dist}
2.0 < 2.0^20250203gitabc1234 < 2.0.1
Снапшоты из git
Когда upstream не делает релизов, а нужна свежая версия из git:
Способ 1: через Release (традиционный)
%global commit abc1234def5678
%global shortcommit %(c=%{commit}; echo ${c:0:7})
%global gitdate 20250203
Version: 1.2
Release: 0.1.%{gitdate}git%{shortcommit}%{?dist}
0.X в Release гарантирует, что снапшот ниже будущего финального 1.2-1:
1.2-0.1.20250203gitabc1234 < 1.2-1
При следующем снапшоте:
Release: 0.2.%{gitdate}git%{shortcommit}%{?dist}
При выходе финального 1.2:
Release: 1%{?dist}
Способ 2: через каретку (современный)
Version: 1.1^20250203gitabc1234
Release: 1%{?dist}
1.1 < 1.1^20250203gitabc1234 < 1.2
Epoch: крайняя мера
Когда использовать
Epoch нужен только когда upstream ломает порядок версий:
Было: 2024.01.15 (версия по дате)
Стало: 1.0.0 (upstream перешёл на semver)
RPM считает 2024.01.15 > 1.0.0, поэтому dnf upgrade не обновит пакет.
Решение:
Epoch: 1
Version: 1.0.0
Release: 1%{?dist}
Теперь 1:1.0.0 > 0:2024.01.15.
Почему Epoch опасен
- Нельзя убрать. Если добавили
Epoch: 1, нельзя потом откатить наEpoch: 0 - Заражает зависимости. Пакеты, зависящие от вашего, должны учитывать Epoch:
# Без Epoch
Requires: libfoo = 1.0.0
# С Epoch
Requires: libfoo = 1:1.0.0
- Усложняет сопровождение навсегда
Альтернативы Epoch
Перед использованием Epoch попробуйте:
-
Переформатировать Version:
# Вместо Epoch Version: 20240115 → Version: 1.0.0~20240115 -
Использовать Obsoletes:
Name: mypackage Version: 1.0.0 Obsoletes: mypackage < 2024.01.16
Сводка правил
| Сценарий | Что делать |
|---|---|
| Новая версия upstream | Version: X.Y.Z, Release: 1%{?dist} |
| Исправление SPEC | Увеличить Release |
| Предрелиз (alpha/rc) | Version: X.Y~rcN |
| Снапшот из git | Release: 0.N.YYYYMMDD... или Version: X.Y^DATE... |
| Upstream сломал нумерацию | Epoch (крайний случай) |
Проверка порядка версий
# Сравнить две версии
rpmdev-vercmp 1.0-1 1.0-2
rpmdev-vercmp 2.0~rc1-1 2.0-1
rpmdev-vercmp 1:1.0-1 2.0-1
# Посмотреть NEVRA установленного пакета
rpm -q --queryformat '%{EPOCH}:%{VERSION}-%{RELEASE}\n' mypackage
Проверьте понимание
- Как RPM сравнивает версии
1.9и1.12? - Что означает тильда в
2.0~rc1? - Когда нужно сбрасывать Release в 1?
- Почему
Release: 0.1.date...гарантирует порядок ниже финального релиза? - Какие альтернативы Epoch можно попробовать?
Следующий модуль: Качество и релиз