Linked vs fixed packages
fixed and linked are molt's two mechanisms for making a set of packages share versions. They sound the same and are constantly confused -- so here is the one-line difference: fixed always releases every member together; linked only aligns the members that were already going to release.
Both are configured as groups of package names in [tool.molt], and both are resolved inside the release plan's fixpoint loop. A package can belong to a fixed group or a linked group, but never both.
Note. changesets ships these two features with near-identical dictionary definitions ("share a semver categorisation..."), which is why nobody can remember which is which. molt states the distinction sharply and keeps
fixedandlinkedas genuinely different tools -- see Why Molt? on the vocabulary molt refuses to inherit.
fixed: move as one, always
A fixed group behaves like a single versioned unit. When any member releases, every member releases -- to one shared version -- even members that nothing changed.
Use fixed when the packages are, for practical purposes, one product with one version number that you always publish in lockstep (think a framework and its official runtime). The cost is churn: a changeset touching only acme-core still forces a fresh acme-http release at the new shared version.
linked: align on release, never force one
A linked group keeps versions consistent among the packages that are releasing anyway, but it never drags in a member that had no reason to release.
Use linked when you want releasing packages to stay on matching version numbers -- so a user never sees acme-core 2.1.0 next to acme-http 2.0.4 -- without publishing untouched packages just to keep the numbers tidy.
The precise difference
Both mechanisms compute the same two things for the group:
- the highest current version among all members, read from disk, and
- the highest bump among the members that are releasing.
They differ only in who the resulting version is applied to:
The contrast in one setup
The cleanest way to see the difference is to run the identical scenario through each mechanism.
Setup. Three packages, grouped together. acme-http gets a minor changeset and acme-core gets a patch changeset. acme-billing has no changeset -- but it already sits at a higher version than the others:
The group's highest current version is 2.0.0 (from acme-billing), and the highest bump among releasing members is minor (from acme-http). So the shared target is inc(2.0.0, minor) = 2.1.0.
With fixed = [["acme-core", "acme-http", "acme-billing"]] -- three releases:
acme-billing is force-released to 2.1.0 even though nothing changed it -- that is fixed.
With linked = [["acme-core", "acme-http", "acme-billing"]] -- two releases:
acme-core and acme-http are pulled up to 2.1.0 (note their oldVersion is realigned to the group max 2.0.0 before the bump), while acme-billing -- which had no reason to release -- stays at 2.0.0 and never enters the plan. That is linked.
Same three packages, same changesets: fixed produces three releases, linked produces two. That single row is the whole distinction.
How they interact with the engine
Both passes run after dependent propagation within each iteration of the fixpoint loop, and both can re-trigger the loop:
- Raising a group to a higher shared version can push a member out of its dependents' ranges, forcing more propagation on the next iteration.
- Because grouping runs after propagation, a group can absorb a propagated bump: if a dependent picks up a
patchfrom propagation but its group is moving byminor, the group'sminoroverwrites thepatch, and the member lands on the group version rather than a stray patch.
Chained groups (where one group depends on another) resolve through the same loop, one pass feeding the next until everything converges.
Choosing between them
- Reach for fixed when the packages are conceptually one release with one version number, and you accept publishing all of them whenever any of them changes.
- Reach for linked when you want matching version numbers among whatever is releasing, without minting releases for untouched packages.
- If neither fits, plain dependent propagation already keeps a workspace correct -- most workspaces need no groups at all.
Where to go next
- The release plan -- the fixpoint loop that resolves both mechanisms.
- Versioning -- running
molt versionand reading the result. - Options -- the
fixedandlinkedconfig keys. - Glossary -- fixed, linked, dependent, and the rest.