by Volker Hilsheimer
In order to sustain vigorous development while maintaining stable releases without subjecting users to disruptive upgrades, the Qt framework has diverse branches, on some of which only the least disruptive of changes are permitted while, on others, developers have more freedom to change APIs and behaviors. The aim of this QUIP is to make clear which changes go into which branches, what stability commitments The Qt Project makes to its users for its various types of release, and how the former ensures the latter.
It supersedes QUIP 5 with the changes discussed at the QtCS2019 Branch Policy Session.
Note 1: The QUIP applies to the normal course of development. Close to feature-freezes, branching and releases, the release team may impose tighter control.
Note 2: The guidelines apply to the Qt frameworks only. Other products (like Qt Creator) may choose a different approach.
Each stable branch is initially stabilized after branching off dev, in preparation for serving as the base for successive release branches. Once stable, the branch generally accepts:
We divide the LTS lifecycle into 3 periods, each lasting roughly 12 months:
stable
Initially, the LTS branch is handled like any stable branch.
strict
This period starts after two subsequent stable branches have been
created (for example, for 6.8 LTS, the second was 6.10). Upgrading the
Qt libraries (within LTS) must not put installed applications at risk of
breaking. Breaking existing bug workarounds is therefore not allowed,
even if the bug is fixed.
very strict
(third year) We only accept fixes to P0 and P1 bugs, which there should
be very few of by this stage.
Note: From 5.15 onwards, the extension of the stable phase becomes a service for users of Qt under the commercial license. The stable phase ends when the next minor or major release is available (typically after 6 months), and strict and very strict phases affect only commercial releases.
Changes are generally developed and submitted against the dev branch. Changes that qualify for a stable, strict, or release branch may be cherry-picked into those branches once the merge into dev is completed. This might require some backporting and adjustments, or even a complete rewrite of the change. All cherry-pick changes need to reference the original commit.
Cherry-picking can be done semi-automatically, using the Pick-to:
footer in the commit message. The Pick-to: footer specifies a
space-separated list of branches into which the change should be
cherry-picked once the patch has been successfully merged.
Each branch listed in the Pick-to: footer will generate a cherry-pick
patch on the target branch based on the latest revision of the merged
patch. The owner of the new patch will be the Qt Cherry-pick Bot, and
the author of the original commit will be the author of the cherry-pick.
If the cherry-pick bot does not encounter any conflicts, the commit will
be automatically approved and staged.
In case of any issues during the process, the original author will be set as the assignee of the cherry-pick patch, and reviewers will be copied from the original change. Author and reviewers will be notified about the issue, and can amend the patch like any regular change review.
To cherry-pick changes manually, use the -x option, and don’t change
the gerrit Change-Id footer. The cherry-pick must be done from the
commit once it has been integrated into the published branch, not from a
branch in a local clone, whose sha1 shall be different from the
published version. Even when the change is a complete rewrite, it shall
reference the original commit in its commit message, using a “fake”
cherry-pick footer following the pattern (adapted from commit <sha1>).
Submit the patch for review like any other change.
Changes should only be made directly on stable branches when there is no matching change to make on dev (e.g. because the code in question has been removed). In such cases, the change should be made on the newest stable branch to which it applies and cherry-picked back to any older stable branch to which it may be relevant.
Submitting changes directly to a strict LTS branch is not possible; changes must be submitted to the stable branch and undergo some testing first before being cherry-picked into a strict LTS branch.
Changes made as part of the release process (such as adding change files) should normally be kept to a minimum. Such changes should be propagated to their stable branch, any more recent stable branches, and dev.
Refactorings generally do not get cherry-picked, with some exceptions:
Refactoring should, wherever possible, be isolated within commits that don’t change externally observable behavior, and thus kept separate from (even if interleaved with) commits that fix bugs (albeit these may exploit the new structure resulting from the refactor to enable their fixes).
The table below lists typical code changes, and indicates with a cross symbol the branches the change may be cherry-picked to. Generally, changes that are more risky or have lower impact should only be cherry-picked to a less stable (i.e. further to the left) branch.
Types of changes not listed here are in general only relevant for the dev branch, and do not get cherry-picked. In particular, any feature addition, refactoring, or adoption of new C++ language features does not get cherry-picked. See the “Exceptions” section for exceptions to this.
In all cases, we need to estimate the impact of the change. For example, a fix for a performance problem may end up in a different branch depending on: how many users are affected, how big is the improvement, and what is the risk of regressions.
| Reason for Change | Stable | LTS | Release | Notes | |
|---|---|---|---|---|---|
| Strict | Very Strict | ||||
| Binary compatibility fix | x | x | x | x | Has to be compatible with all versions |
| Source compatibility fix | x | x | x | x | Has to be compatible with all versions |
| API review finding | x | x | Initial release only (6.x.0) | ||
| RTA/package test finding | x | x | x | x | |
| Security issue | x | x | x | x | |
| Update 3rd party component | x | x | |||
| Update security critical 3rd party component | x | x | x | ||
| Adapt to minor OS/Compiler updates | x | x | x | ||
| Memory leak | x | x | |||
| Feature added in this minor version | x | x | |||
| Undefined behavior | x | x | |||
| Something that makes existing apps unstable | x | x | |||
| Performance: significant fix improving O() | x | x | |||
| Performance: Issue detected by profiling | x | ||||
| Compiler warnings | x | x | |||
| False positives raised by tools | x | e.g. static code analysers | |||
| Documentation: small fixes (links, typos, warnings) | x | x | x | ||
| Documentation: refactoring | x | ||||
| Tests: flakiness | x | x | x | ||
| Tests: refactoring | x | ||||
| Bugs: Easily triggered crash | x | x | x | ||
| Bugs: Hard to reproduce crash | x | x | |||
| Bugs: Regression | x | x | |||
| Bugs: Hard-to-reproduce regression noticed some time after release | x | ||||
| Bugs: Other | x | ||||
| Refactoring: for bug fix | * | * | * | * | * Branch depends on severity of bug; i.e. a refactoring for a security fix goes to all branches |
RTA
Release testing automation
QtCS2019 Branch Policy Session: https://wiki.qt.io/Qt_Contributors_Summit_2019_-_Branch_Policy