Tracking modes and resolution¶
How each tracking mode picks a commit, using only the refs that exist locally.
Tracking modes¶
Mode |
Option |
Example ref |
Behaviour |
|---|---|---|---|
|
|
|
Floating: |
|
|
|
Pinned: |
|
|
|
|
|
|
|
Pinned to a commit: |
Choose branch for dependencies you develop alongside the superproject,
tag-pattern for releases you want to follow within a series, and tag
or commit for dependencies that must not move without a deliberate
change.
Resolution is local¶
status and verify never fetch, and update fetches only with
--fetch. They resolve refs in what the last fetch left behind:
in the submodule’s working tree, when it is checked out;
otherwise in its Git directory under
.git/modules/, for example aftergit submodule deinit.
Run lazysubmodules fetch, or update --fetch, to see what the remotes
offer now. The remote is always the one named origin.
This keeps the network use predictable, and it makes a dry run, a
status and an update agree with each other: they all see the same
refs.
Per mode¶
branchResolves
refs/remotes/origin/<branch>in the submodule, the remote-tracking branch as of the last fetch. A local branch of the same name does not matter.tagResolves
refs/tags/<tag>. An annotated tag is dereferenced to its commit, as withgit rev-parse "<tag>^{commit}".tag-patternLists the local tags that match the pattern, sorts them by version and takes the highest one that qualifies (see below).
commitResolves the configured SHA, which may be abbreviated to 7 digits or more. It must exist locally and be unambiguous; a ref of the same spelling makes it ambiguous. The lock file records the full SHA.
How a tag pattern selects a tag¶
Match. The pattern is a glob, as
git tag --listaccepts it.*matches any characters, including dots.Sort. The candidates are sorted by version, highest first:
git -c versionsort.suffix=- tag --list <pattern> --sort=-v:refname
Numbers compare as numbers, so
v1.10.0sorts abovev1.9.0, and because ofversionsort.suffix=-,v1.0.0-rc.1sorts belowv1.0.0.Skip pre-releases. A tag with a
-anywhere after its first digit is a pre-release:v1.0.0-rc.1andv6.6-rc3are pre-releases,release-2.1is not. Pre-releases are skipped unlessupdateoraddis given--include-prerelease.Keep the locked tag. The tag in the lock entry stays a candidate even when it is a pre-release (see below).
Select the highest remaining candidate.
In the demo, kernel has the tags v6.6.1 to v6.6.10, v6.6.11-rc1
and v6.7-rc1, and its lock entry records v6.6.9:
The same tags, selected by v6.6.*, by v6.6.* with
--include-prerelease, and by v6.*.
Chapter 5 of the demo shows the second case, with the pre-release selected on request:
$ lazysubmodules update --dry-run --include-prerelease kernel sdk
would update kernel: v6.6.9 (8106f61) -> v6.6.11-rc1 (50d5d57)
sdk: up to date
sdk is up to date here because v3.0.0-rc.2 is its highest tag. The
next rule explains why it stays there without --include-prerelease.
Never downgrade¶
In tag-pattern mode, the tag recorded in .lsm.lock stays a candidate
as long as it still exists locally and matches the pattern, even when it
is a pre-release. An update therefore never moves back to an older tag
just because the newer one is a pre-release.
The demo’s sdk follows v* and is locked at the release candidate
v3.0.0-rc.2. The newest stable tag is v2.9.0, but a plain update
keeps the release candidate:
$ lazysubmodules update --dry-run sdk
sdk: up to date
$ git -C sdk -c versionsort.suffix=- tag --list 'v*' --sort=-v:refname
v3.0.0-rc.2
v3.0.0-rc.1
v2.9.0
Once upstream releases v3.0.0 and you fetch it, the submodule moves on,
because v3.0.0 sorts above v3.0.0-rc.2. From chapter 8 of the demo:
$ lazysubmodules update --commit fpga.core sdk
fpga.core: v2.3.1 (556baa1) -> v2.3.1 (7c6069a)
sdk: v3.0.0-rc.2 (6308203) -> v3.0.0 (599ca2a)
committed 878b0f15f9949a97c856cfbbc1655f9f15cffd18
Without this rule, an update after update --include-prerelease would
jump back to the newest stable release, and the next
--include-prerelease would jump forward again.
The rule applies only to tag patterns. In tag mode, update moves to
the configured tag even when it is older than the locked one, because
you asked for exactly that tag.
What status compares¶
status resolves the target the same way, and reports
behind when the result differs from the
lock entry in its mode, its ref or its commit. A difference between HEAD
and the lock entry is drift instead, which
status checks first; see Precedence. For branches,
behind means “behind the remote-tracking branch as of the last fetch”:
after a fetch, a submodule that was ok can become behind without any
local change.
See also¶
Change what a submodule tracks, with a recipe for release series.
.lsm.lock: what the lock entry records per mode.
update: the options
--fetchand--include-prerelease.