Richtlinien für die Versionierung

Das Versionsverwaltungssystem von Fedora umfasst sowohl die Tags Version: und Release: als auch Epoch:. Das übergeordnete Ziel ist es, Paketsequenzen bereitzustellen, die vom Versionsvergleichsalgorithmus von RPM als Aktualisierungen behandelt werden, und gleichzeitig die unterschiedlichen und oft inkonsistenten Versionsverwaltungssysteme der Upstream-Bibliotheken zu berücksichtigen.

Das Feld Version: enthält die Version des Upstream-Projekts, und das Feld Release: gibt die Downstream-Releasenummer an.

Einige Definitionen

Beachten Sie, dass die jeweiligen Upstream-Projekte ihre eigene Terminologie verwenden können und es generell unmöglich ist, diese Begriffe vollständig allgemein zu definieren. Bei manchen Upstream-Projekten gilt jeder Commit als Version. Andere veröffentlichen nie Releases, sondern stellen den Nutzern einfach den jeweils verfügbaren Code aus dem Repository zur Verfügung.

„release version“

Eine Softwareversion, deren Veröffentlichung vom Upstream-Projekt beschlossen wurde. Die Veröffentlichung kann so einfach sein wie das Hinzufügen eines Git-Tags. Dies umfasst sogenannte „Point Releases“ oder „Patchlevel“, die von einigen Upstream-Projekten erstellt werden, da es sich dabei um zugewiesene und veröffentlichte Versionen handelt.

„snapshot“

Ein Archiv aus dem Quellcodeverwaltungssystem des Upstream-Projekts, das keiner Release-Version zugeordnet ist.

„prerelease version“

Vor einer Veröffentlichung legen viele Upstream-Entwickler fest, welche Version veröffentlicht werden soll, und erstellen dann sogenannte „Alphas“, „Betas“, „Release Candidates“ oder Ähnliches. Diese Versionen enthalten zwar bereits die neue Versionsnummer, weisen aber auch darauf hin, dass die Veröffentlichung noch nicht erfolgt ist. Wir bezeichnen diese Versionen als Vorabversionen. Auch alle Snapshots, die während der Vorbereitungsphase der Upstream-Entwickler erstellt werden, gelten als Vorabversionen.

„postrelease version“

Jede Version, die nach einer bestimmten Veröffentlichung erscheint, ist technisch gesehen eine „Post-Release“-Version. Bevor die Entwickler jedoch mit der Erstellung von Vorabversionen für die nächste Version beginnen, wird jeder Snapshot als Post-Release-Version betrachtet.

Unsortierte Versionssequenz

Eine Folge von Versionszeichenketten, die nicht der Reihenfolge der Versionsvergleichsfunktion von RPM entspricht. RPM verwendet eine relativ komplexe Versionsvergleichsfunktion, um festzustellen, ob ein Paket „neuer“ ist. Weicht die Definition einer „neueren“ Version durch den Entwickler von der RPM-Implementierung ab, führt die direkte Verwendung der Entwicklerversionen zu Aktualisierungen, die tatsächlich keine Pakete aktualisieren.

Epoch-Tag

Das Tag Epoch: liefert den wichtigsten Input für die Versionsvergleichsfunktion von RPM. Falls vorhanden, muss es aus einer positiven Ganzzahl bestehen. Es sollte nur eingeführt oder erhöht werden, wenn dies notwendig ist, um Probleme mit der Reihenfolge zu vermeiden. Das Tag Epoch: darf, sobald es einem Paket hinzugefügt wurde, niemals entfernt oder verringert werden.

Release-Tag

Der Release:-Tag sollte automatisch mithilfe des Makros %autorelease verwaltet werden:

Release: %autorelease

Wie in der Dokumentation zu %autorelease beschrieben, ersetzt der Build-Mechanismus das Makro durch die Anzahl der Bauvorgänge seit dem letzten Commit, der das Feld Version geändert hat, ergänzt durch den Tag %{?dist}. Das bedeutet, dass ein Commit, der Version ändert, automatisch Release: 1%{?dist} erhält, und nachfolgende Commits erhalten Release: 2%{?dist}, Release: 3%{?dist} usw.

Alternativ kann das Feld Release: manuell aktualisiert werden. Siehe Traditionelle Versionierung mit einem Teil der Upstream-Versionsinformationen im Release-Feld.

Einfache Versionierung

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.

Komplexe Versionierung

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.

The caret operator is not supported in RHEL7 which has rpm 4.11. If you need to support RHEL7/EPEL7 from the same specfile, use [Traditional versioning with part of the upstream version information in the release field] instead.

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

Das Upstream-Projekt hat nie eine Version verwendet

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

Das Upstream-Projekt verwendet in der Versionierung unzulässige Zeichen

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.

Nicht sortierbare Versionen

Wenn das Upstream-Projekt ein Versionierungsschema verwendet, das nicht sauber sortiert, prüfen Sie zunächst, ob das Einfügen einer Tilde oder eines Carets ausreicht, um die Zeichenkette sortierbar zu machen.

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.

Beispiele

Versionsvergleich mit rpmdev-vercmp

Im Zweifelsfall überprüfen Sie die Sortierung mit rpmdev-vercmp aus dem Paket rpmdevtools:

==== Einfache Versionierung

[%header]
|===
|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.fc{CURRENTVER}` (immediately after an update) or `pkg-1.2.1-5.fc{CURRENTVER}` (after downstream rebuilds with the same upstream version).

[%header]
|===
|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.fc{CURRENTVER}`.

==== Complex versioning with a reasonable upstream

[%header]
|===
|Upstream version | Version tag | Notes

| 1.0.0-rc1 | `+1.0.0~rc1+` | first prerelease

| 1.0.0-rc2 | `+1.0.0~rc2+` | second prerelease

| 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.fc{CURRENTVER}` (if many rebuilds were done).

==== Complex versioning with non-sorting upstream post-release versions

[%header]
|===
|Upstream version | Version tag | Notes

| 1.1.0~BETA      | `+1.1.0~BETA+` | this is a prerelease, first beta

| 1.1.0~BETA1     | `+1.1.0~BETA1+` | this is a prerelease, second beta

| 1.1.0~BETA2     | `+1.1.0~BETA2+` | this is a prerelease, third beta

| 1.1.0~CR1       | `+1.1.0~CR1+` | this is a prerelease, candidate release 1

| 1.1.0~CR2       | `+1.1.0~CR2+` | this is a prerelease, 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.fc{CURRENTVER}`.

==== Complex versioning with a pre- and post-release snapshots

[%header]
|===
|Upstream version | Version | Notes

| 1.0.0-rc1            | `+1.0.0~rc1+` | First prerelease

| 1.0.0-rc2            | `+1.0.0~rc2+` | Second prerelease

| git commit `f00fabd` | `+1.0.0~rc2^20210101gf00fabd+` | Post-prerelease 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.fc{CURRENTVER}`.

[#traditional-versioning]
== Traditionelle Versionierung mit einem Teil der Upstream-Versionsinformationen im Release-Feld

The method described in this section is deprecated, but **may** be used. As mentioned in the xref:_handling_non_sorting_versions_with_tilde_dot_and_caret[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.

Bei dieser Methode wird `+%autorelease+` nicht verwendet, und das Feld `Release` muss manuell verwaltet werden.

Diese Methode zur Behandlung der meisten Vor- und Nachveröffentlichungsversionen sowie nicht sortierbarer Versionen beinhaltet das mögliche Entfernen einiger Informationen aus dem `+Version:+`-Tag und das Hinzufügen einer zusätzlichen Struktur zum `+Release:+`-Tag. Der strukturierte `+Release:+`-Tag kann potenziell aus vier Feldern bestehen:

* Release-Nummer des Pakets (`+<pkgrel>+`)
* Zusätzliche Versionsinformationen (`+<extraver>+`)
* Snapshot-Information (`+<snapinfo>+`)
* minor release bump (`+<minorbump>+`)

Die Release-Nummer des Pakets **muss** immer angegeben werden, während die anderen Angaben je nach Situation vorhanden sein können oder nicht.

Die vorhandenen Elemente werden (durch Punkte getrennt) zum endgültigen `+Release:+`-Tag kombiniert. In der üblichen Notation, wobei eckige Klammern optionale Elemente kennzeichnen:

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

The actual values to be used for those three fields 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.

=== Nicht sortierbare Versionen

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.

Falls dies nicht möglich ist, verwenden Sie „Version: 0“ und verschieben Sie die _gesamte_ Versionszeichenkette in `+<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:

* `+JJJJMMTT.<Revision>+`
* `+YYYYMMDD<scm><revision>+`

Where `+<scm>+` is a short string identifying the source code control 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 control system. Obviously if CVS is used, no such revision information exists, so it would be omitted, but otherwise it **should** be included.

=== Vorabversionen

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. Prerelease versions **must** use a `+Release:+` tag strictly less than 1, as this is the sole indicator that a prerelease 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 F{CURRENTVER} that still compares lower than the one in F{NEXTVER}. 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.

=== Beispiele

Viele mögliche Szenarien der traditionellen Versionierung finden Sie in den https://fedoraproject.org/wiki/Package_Versioning_Examples[Beispielen zur Paketversionierung].


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