Versioning Guidelines
Fedora’s package versioning scheme
encompasses both the Version:
and Release: tags, as well as Epoch:.
The overriding goal is to provide sequences of packages
which are treated as updates by RPM’s version comparison algorithm
while accommodating varied and often inconsistent upstream versioning schemes.
The Version: field contains the upstream project version,
and the Release: field specifies the downstream release number.
Some definitions
Note that upstreams may each have their own terminology and it is in general impossible to define these terms with complete generality. For some upstreams, every commit is itself considered a version. Some upstreams never make releases, instead just letting users take whatever is in the code repository at any given time.
- release version
-
A version of the software which upstream has decided to release. The act of releasing the software can be as simple as adding a git tag. This includes so-called "point releases" or "patchlevels" which some upstreams make, since those are actually assigned versions and released.
- snapshot
-
An archive taken from upstream’s source code control system which is not associated with any release version.
- prerelease version
-
Before a release happens, many upstreams will decide which version that will release will have, and then produce "alphas", "betas", "release candidates", or the like which carry that new version but indicate that the release of that version has not yet been made. These we call prerelease versions. Any snapshots made while upstream is preparing for their release are also considered prerelease versions.
- postrelease version
-
Any version which happens after a particular release is technically "post-release", but before upstream begins making prereleases for the next version, any snapshot is considered a postrelease version.
- non-sorting version sequence
-
A sequence of version strings which is not ordered in the same way that RPM’s version comparison function would order it. RPM has a somewhat complicated version comparison function which it will use to determine if a package is "newer". If upstream’s idea of what constitutes a "newer" version differs from RPM’s implementation then simply using upstream’s versions directly will result in updates which don’t actually update any packages.
Epoch tag
The Epoch: tag provides the most significant input to RPM’s version comparison function.
If present, it must consist of a positive integer.
It should only be introduced or incremented
when necessary to avoid ordering issues.
The Epoch: tag, once introduced to a package,
must never be removed or decreased.
Release tag
The Release: should be managed automatically using the %autorelease macro:
Release: %autorelease
As described in
%autorelease documentation,
the build machinery will
replace the macro with the number of builds since the last commit that changed the Version field,
suffixed with the %{?dist} tag.
This means that a commit that changes Version automatically gets Release: 1%{?dist},
and commits after that get Release: 2%{?dist}, Release: 3%{?dist}, and so on.
Alternatively, the Release: field may be updated manually.
See Legacy complex versioning
in the appendix for more information.
Simple versioning
Most upstream versioning schemes are "simple";
they generate versions like 1.2.03.007p1.
They consist of one or more version components, separated by periods.
Each component is a whole number, potentially with leading zeroes.
The components can also include one or more ASCII letters, upper or lower case.
The value of a component must never be reduced (to a value which sorts lower)
without a component somewhere to the left increasing.
Note that the version sequence (1.4a, 1.4b, 1.4)
does not meet this criterion,
as 4 sorts lower than 4b.
The sequence (1.4, 1.4a, 1.4b) is, however, simple.
This is a very common versioning scheme, and the vast majority of software projects use something which works like this.
To package release versions of software using this versioning scheme:
-
Use the upstream project version verbatim in the
Version:tag. Don’t trim leading zeroes.
Complex versioning
There are several ways in which the simple scheme might not work in a particular situation:
-
Upstream has never chosen a version; only snapshots are available for packaging.
-
Upstream simply doesn’t use a version scheme which orders properly under RPM’s version comparison operation.
-
You wish to package a prerelease version (snapshot or otherwise).
-
You wish to package a postrelease snapshot.
-
Upstream was thought to be following one scheme but then changed in a way that does not sort properly.
-
You need to apply a small fix to a release branch of Fedora without updating the newer branches.
-
More than one of the above may apply (lucky you). Follow all of the relevant recommendations below together.
This subsection describes how to modify the upstream project version to be suitable for the Version field.
Use of Release: %autorelease remains unchanged.
Handling non-sorting versions with tilde, dot, and caret
The tilde symbol (‘~’) is used before a version component which must sort earlier than any non-tilde component. It is used for any pre-release versions which wouldn’t otherwise sort appropriately.
For example, with upstream releases 0.4.0, 0.4.1, 0.5.0-rc1, 0.5.0-rc2, 0.5.0,
the two "release candidates" should use 0.5.0~rc1 and 0.5.0~rc2 in the Version: field.
Bugfix or "patchlevel" releases that some upstream make should be handled using simple versioning. The separator used by upstream may need to be replaced by a dot or dropped.
For example, if the same upstream released 0.5.0-post1 as a bugfix version,
this "post-release" should use 0.5.0.post1 in the Version: field.
Note that 0.5.0.post1 sorts lower than both 0.5.1 and 0.5.0.1.
The caret symbol (‘^’) is used before a version component which must sort later than any non-caret component. It is used for post-release snapshots, see next section.
Snapshots
Snapshots (a version taken from the upstream source control system not associated with a release),
must contain a snapshot information field after a caret (^).
The first part of the field ensures proper sorting.
That field may either be the date in eight-digit "YYYYMMDD" format,
which specifies the last modification of the source code,
or a number.
The packager may include up to 17 characters of additional information after the date,
specifying the version control system and commit identifier.
The snapshot information field is appended to version field described above,
possibly including the pre-release and patchlevel information.
One of the following formats should be used for the snapshot information field:
-
<date>.<revision> -
<date><scm><revision> -
<number>.<revision> -
<number>.<scm><revision> -
<scm><date>.<revision> -
<scm><number>.<revision>
Where <scm> is a short string
identifying the source code control system upstream uses
(e.g. "git", "svn", "hg") or the string "snap".
The <scm> string may be abbreviated to a single letter.
<revision> is either a short git commit hash, a subversion revision number,
or something else useful in identifying the precise revision in upstream’s source code control system.
If the version control system does not provide an identifier (e.g. CVS), this part should be omitted.
A full hash should not be used for <revision>, to avoid overly long version numbers;
only the first 7 to 10 characters.
For example, if the last upstream release was 0.4.1,
a snapshot could use 0.4.1^20200601g01234ae in the Version: field.
Similarly, if the upstream then makes a pre-release with version 0.5.0-rc1,
but it is buggy, and we need to actually package two post-pre-release snapshots,
those shapshots could use 0.5.0~rc1^20200701gdeadf00f and 0.5.0~rc1^20200702gdeadaeae
in the Version: field.
Alternatively, those three snapshots could be versioned as
0.4.1^1.git01234ae, 0.5.0~rc1^1.gitdeadf00f and 0.5.0~rc1^2.gitdeadaeae.
Note that 0.4.1^<something> sorts higher than 0.4.1, but lower than both 0.4.2 and 0.4.1.<anything>.
Upstream has never chosen a version
When upstream has never chosen a version,
you must use Version: 0.
"0" sorts lower than any other possible value that upstream might choose.
If upstream does choose to release "version 0",
then just set Release: higher than the previous value.
(When %autorelease is used, this happens automatically.)
Upstream uses invalid characters in the version
It’s possible that upstream uses characters besides ASCII letters (upper and lower case), digits and periods in its version. They must be removed and potentially replaced with valid characters. Any such alterations must be documented in the specfile. It is not possible to cover all potential situations here, so it is left to the packager to alter the upstream versioning scheme consistently.
After altering the version to be free of invalid characters, see Unsortable versions below if the modifications, when applied to successive releases from upstream, will not order properly.
Unsortable versions
When upstream uses a versioning scheme that does not sort properly, first see if simply inserting a tilde or caret is enough to make the string sortable.
For example, if upstream uses a sequence like 1.2pre1, 1.2pre2, 1.2final,
then 1.2~pre1, 1.2~pre2, 1.2_final could be used as Version.
The underscore (‘_’) is a visual separator that does not influence sort order,
and is used here because "final" does not form a separate version component.
If this is not possible, use something similar to the snapshot version information field described above,
with the upstream version moved to the second part of the snapshot information field:
<date>.<version>.
For example, if upstream releases versions I, II, …, VIII, IX
use 20200101.I, 20200201.II, …, 20200801.III, 20200901.IX
in the Version field.
Upstream breaks version scheme
It is possible that upstream simply adopts a different versioning scheme,
fails to follow an expected pattern,
or even simply resets their version to some lower value.
If none of the above operations can help
with giving a version which sorts properly,
or give you a version which sorts lower
than the packages already in Fedora,
then you have little recourse but to increment the Epoch: tag,
or to begin using it by adding Epoch: 1.
At the same time, try to work with upstream
to hopefully minimize the need to involve Epoch: in the future.
Examples
Comparing versions with rpmdev-vercmp
When in doubt, verify the sorting with rpmdev-vercmp from the rpmdevtools package:
$ rpmdev-vercmp 2~almost^post 2.0.1
2~almost^post < 2.0.1
Simple versioning
| Upstream version | Version tag | Explanation |
|---|---|---|
1.0 |
1.0 |
The first release. |
1.1 |
1.1 |
An upstream update. |
1.2.1 |
1.2.1 |
Another upstream update. Extra levels of versioning are OK… |
1.3 |
1.3 |
…they can come and go without problems. |
In this case the full N-V-R could be e.g. pkg-1.2.1-1.fc38 (immediately after an update)
or pkg-1.2.1-5.fc38 (after downstream rebuilds with the same upstream version).
| Upstream version | Version tag | Explanation |
|---|---|---|
5.2 |
5.2 |
Upstream release. |
5.2a |
5.2a |
Upstream introduced a letter to indicate a patch release. You trust upstream to use letters in alphabetical order, so it’s OK to use the version as is. |
5.2b |
5.2b |
Another patch release after 5.2 — this is not a beta. |
5.2b.1 |
5.2b.1 |
Even this is OK as long as the sequence increases. |
5.3 |
5.3 |
Another upstream release. |
In this case the full N-V-R could be e.g. pkg-5.2b.1-1.fc38.
Complex versioning with a reasonable upstream
| Upstream version | Version tag | Notes |
|---|---|---|
1.0.0-rc1 |
|
first prerelease |
1.0.0-rc2 |
|
second prerelease |
1.0.0 |
|
release |
1.0.1 |
|
bugfix release |
1.0.1-security1 |
|
security bufix release |
In this case the full N-V-R could be e.g. pkg-1.0.0~rc2-42.fc38 (if many rebuilds were done).
Complex versioning with non-sorting upstream post-release versions
| Upstream version | Version tag | Notes |
|---|---|---|
1.1.0~BETA |
|
this is a prerelease, first beta |
1.1.0~BETA1 |
|
this is a prerelease, second beta |
1.1.0~BETA2 |
|
this is a prerelease, third beta |
1.1.0~CR1 |
|
this is a prerelease, candidate release 1 |
1.1.0~CR2 |
|
this is a prerelease, candidate release 2 |
1.1.0-1% |
|
final release |
1.1.0-GA1 |
|
post release, GA1 |
1.1.0-CP1 |
|
post release, CP1, after GA1, does not sort properly |
1.1.0-CP2 |
|
post release, CP2, after CP1 |
1.1.0-SP1 |
|
post release, SP1, after CP2 |
1.1.0-SP1-CP1 |
|
post release, SP1_CP1, after SP1 |
In this case the full N-V-R could be e.g. pkg-1.1.0.20210105.SP1_CP1-1.fc38.
Complex versioning with a pre- and post-release snapshots
| Upstream version | Version | Notes |
|---|---|---|
1.0.0-rc1 |
|
First prerelease |
1.0.0-rc2 |
|
Second prerelease |
git commit |
|
Post-prerelease snapshot |
1.0.0 |
|
A release |
1.0.1 |
|
A bugfix release |
git commit |
|
A snapshot |
1.0.1-security1 |
|
A security bufix release. From past history we know that the bugfix releases will have sortable versions. If not, we could use ‘<date>.security1’ instead. |
git commit |
|
Another snapshot |
In this case the full N-V-R could be e.g. pkg-1.0.1.security1^20210301gabc0202-1.fc38.
Rawhide is allowed to lag temporarily
A package may temporarily have a lower EVR in Rawhide when compared to a release branch of Fedora ONLY in the case where the package fails to build in Rawhide. This permits important updates to be pushed to existing Fedora releases regardless of the current state of Rawhide.
Want to help? Learn how to contribute to Fedora Docs ›