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.

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 "patch levels" which some upstreams make, since those are actually assigned versions and released.

pre-release version

Before a release happens, some upstreams will decide which version that 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 are known as pre-release versions.

post-release version

This is similar to pre-release versions, but less common. Functionally these can be treated like a later point release. The important part to ensure they sort after the release version they are relative to, but before any version that upstream intends to supercede them.

snapshot

An archive taken from the upstream’s source code management system that is not directly associated with any release version.

post-release snapshot

A snapshot that is a later revision of the code than an existing release version. This kind of snapshot will often identify itself in code or metadata as the previous release version.

pre-release snapshot

A snapshot that is an earlier revision of the code than a future release version, or than a future pre-release version. This kind of snapshot will often identify itself in code or metadata as the future release 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. It is primarily used to force correct sorting of otherwise non-sorting version sequences from upstream. Most packages will never need to use this tag. 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 NOT ever be removed or decreased.

Version tag

The Version tag SHOULD contain the upstream project version. This tag MAY diverge from the upstream project version when necessary for the following reasons:

Release tag

The Release tag 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 tag, 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 the legacy versioning section below.

Simple versioning

Most upstream versioning schemes are "simple"; they generate versions like 1.2 or 2024.09.06. 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 NOT ever 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. If that sequence was instead (1.4, 1.4a, 1.4b), it would be simple and valid.

To package release versions of software using simple versioning, use the upstream project version verbatim in the Version tag. Do not trim leading zeroes.

Complex versioning

There are several ways in which the simple versioning scheme might not work in a particular situation:

  • Upstream has never chosen a version.

  • You wish to package a snapshot.

  • You wish to package a pre-release version.

  • Upstream doesn’t use a version scheme which orders properly under RPM’s version comparison operation.

  • Upstream changed their version scheme 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 tag. Use of Release: %autorelease remains unchanged.

Character replacements

Some upstreams will release "post" or "patch" versions after a regular version but before the next regular version. These can usually be handled with simple versioning with some slight adjustments. Any invalid characters MUST be replaced or removed. A packager MAY replace the valid separator characters underscore (_) and plus (+) with periods.

For example, with upstream releases 0.5.0, 0.5.0-post1, and 0.5.1, the "post-release" version should use 0.5.0.post1 in the Version tag. Note that 0.5.0.post1 sorts lower than both 0.5.1 and 0.5.0.1.

Non-sorting pre-release versions

A tilde (~) 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. It is also used for pre-release snapshots, which is covered in the next section.

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 tag.

Snapshots

A package using a snapshot MUST use the following format for the Version tag.

Version: <base-version><sort-character><number>.<revision>
  • <base-version>: The version the snapshot is relative to. The snapshot will often identify itself in code or metadata as this version.

  • <sort-character>: A tilde (~) for a pre-release snapshot, or a caret (^) for a post-release snapshot.

  • <number>: An integer that is used for sorting multiple consecutive snapshots. This integer SHOULD be 1 for the first snapshot after a non-snapshot version, and incremented for each subsequent snapshot until the next non-snapshot version. You MAY instead use a date in eight-digit "YYYYMMDD" format, specifying the last modification to the source code. Note that using a date instead of a simple incrementing integer means you cannot release two snapshots from the same day.

  • <revision>: An identifier corresponding to the precise revision in the upstream source code management system. Some examples include a short git commit hash or a subversion revision number. If the upstream uses multiple source code management systems, use the revision from the primary one. If the source code management system does not provide an identifier (e.g. CVS), this part should be omitted. To avoid overly long versions, limit the revision to the first 7 to 10 characters instead of the full hash.

For example, if you want to package a snapshot from commit a1b2c3d that was made after version 0.4.1, the Version tag would be 0.4.1^1.a1b2c3d. Note that 0.4.1^<something> sorts higher than 0.4.1, but lower than both 0.4.2 and 0.4.1.<anything>.

Similarly, if you want to package a snapshot from commit d3c2b1a that is leading up to version 0.4.2, the Version tag would be 0.4.2~1.d3c2b1a. Note that 0.4.2~<something> sorts lower than 0.4.2, but higher than both 0.4.1 and 0.4.1.<anything>.

You can also package a snapshot following a pre-release version. If the upstream makes a pre-release version 0.5.0-rc1, but you want to package a snapshot from commit a3b2c1d that occured afterwards (but still before the 0.5.0 version), the Version tag would be 0.5.0~rc1^1.a3b2c1d.

Upstream has never chosen a version

When upstream has never chosen a version, you MUST use a base version of 0, followed by pre-release snapshot notation.

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 tag.

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

1.0.0~rc1

first pre-release

1.0.0-rc2

1.0.0~rc2

second pre-release

1.0.0

1.0.0

release

1.0.1

1.0.1

bugfix release

1.0.1-security1

pkg-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

1.1.0~BETA

this is a pre-release, first beta

1.1.0~BETA1

1.1.0~BETA1

this is a pre-release, second beta

1.1.0~BETA2

1.1.0~BETA2

this is a pre-release, third beta

1.1.0~CR1

1.1.0~CR1

this is a pre-release, candidate release 1

1.1.0~CR2

1.1.0~CR2

this is a pre-release, candidate release 2

1.1.0-1%

1.1.0

final release

1.1.0-GA1

1.1.0.20201001.GA1

post release, GA1

1.1.0-CP1

1.1.0.20201011.CP1

post release, CP1, after GA1, does not sort properly

1.1.0-CP2

1.1.0.20201101.CP2

post release, CP2, after CP1

1.1.0-SP1

1.1.0.20210101.SP1

post release, SP1, after CP2

1.1.0-SP1-CP1

1.1.0.20210105.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

1.0.0~rc1

First pre-release

1.0.0-rc2

1.0.0~rc2

Second pre-release

git commit f00fabd

1.0.0~rc2^20210101gf00fabd

Post pre-release snapshot

1.0.0

1.0.0

A release

1.0.1

1.0.1

A bugfix release

git commit bbbccc0

1.0.1^20210203gbbbccc0 or pkg-1.0.1^1.gbbbccc0

A snapshot

1.0.1-security1

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 abc0202

1.0.1.security1^20210301gabc0202 or pkg-1.0.1.security1^1.gabc0202

Another snapshot

In this case the full N-V-R could be e.g. pkg-1.0.1.security1^20210301gabc0202-1.fc38.

Legacy versioning with part of the upstream version information in the Release tag

The method described in this section is deprecated, but MAY be used. As mentioned in the Handling non-sorting versions with tilde, dot, and caret section above, this method is recommended for packages with complex versioning when supporting RHEL7 and other systems with old rpm versions.

In this method, %autorelease is not used, and the Release tag must be managed manually.

This method for dealing with most pre- and post-release versions and unsortable versions involves potentially removing some information from the Version: tag while imposing additional structure onto the Release: tag. There are potentially four sections which comprise the structured Release tag:

  • package release number (<pkgrel>)

  • extra version information (<extraver>)

  • snapshot information (<snapinfo>)

  • minor release bump (<minorbump>)

The package release number MUST always be present while the others may or may not be depending on the situation.

Those items which are present are combined (with periods to separate them) to construct the final Release: tag. In the usual notation where square brackets indicate that an item is optional:

<pkgrel>[.<extraver>][.<snapinfo>]%{?dist}[.<minorbump>]

The actual values to be used for those three sections are situational and are referenced in the sections below. Note that your particular situation might not result in the use of <extraver> or <snapinfo>, and in most situations <minorbump> won’t be used at all. Simply do not include those which you don’t have.

Note that the dist tag is supplied by other portions of the system and may in some circumstances contain additional structure, including tildes. As this is not under the control of the packager, that structure is not covered here. The packager MUST simply include %{?dist} verbatim as indicated above.

Unsortable versions

When upstream uses a versioning scheme that does not sort properly, first see if there is any portion which can be removed from the right side of the version string such that the remainder is sortable. This is often possible if upstream uses a sequence like ("1.2pre1", "1.2pre1", "1.2final"). If so, use the removed portion as <extraver> above, and the remainder as the package version. If this splitting leaves a leading or trailing period in either value, remove it.

If this is not possible, use Version: 0 and move the entire version string into <extraver>.

Snapshots

All snapshots MUST contain a snapshot information field (<snapinfo>:) in the Release: tag. That field must at minimum consist of the date in eight-digit "YYYYMMDD" format. The packager MAY include up to 17 characters of additional information after the date. The following formats are suggested:

  • YYYYMMDD.<revision>

  • YYYYMMDD<scm><revision>

Where <scm> is a short string identifying the source code management system upstream uses (e.g. "git", "svn", "hg") or the string "snap". <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 management system. Obviously if CVS is used, no such revision information exists, so it would be omitted, but otherwise it SHOULD be included.

Pre-release versions

In the Version tag, use the version that upstream has determined the next release will be. For the field of the Release tag, use a number of the form "0.N" where N is an integer beginning with 1 and increasing for each revision of the package. Pre-release versions MUST use a Release: tag strictly less than 1, as this is the sole indicator that a pre-release has been packaged.

Release and post-release versions

For the <pkgrel> field of the Release: tag, use an integer beginning with 1 and increasing for each revision of the package. Release and post-release versions MUST use a Release: tag greater than or equal to 1.

Rebuilds in older branches using <minorbump>

In the situation described in [Only an old branch needs a change], you MAY adjust the Release by appending a number after the dist tag, creating a E-V-R for F38 that still compares lower than the one in F39. Set <minorbump> to an in integer beginning with '1' and increase it by one for each minor bump you need to do. Remove <minorbump> once you are able to increase the package release normally without introducing ordering issues.

Examples

Examples of many possible versioning scenarios of traditional versioning are available from Package Versioning Examples.

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.