How It Works
The version resolution engine follows a deterministic algorithm in one of two modes:
| Condition | Result |
|---|---|
| HEAD has valid annotated tag AND clean worktree | Concrete Version |
| Otherwise | Development Version |
"Dirty" includes modified tracked files and untracked files (excluding ignored).
Concrete Version
At a clean tagged commit, the engine returns the exact tag:
Tag: v2.3.1
Result: 2.3.1
Development Version
Between releases, the engine computes a target version:
Priority Order
- Valid target directive — explicit
target: X.Y.Zin commits - Absolute sets —
version: major: 3(highest per component) - Relative changes —
version: majororbreaking:(coalesced) - Default fallback:
- Base is pre-release → core unchanged
- Base is final → patch + 1
- No base, repo has tags → highest major + 1
- No tags anywhere →
0.1.0
Metadata Identifiers
The resolution engine attaches build metadata to development versions in the following order:
| Order | Identifier | Condition |
|---|---|---|
| 1 | pr<N> |
PR number provided |
| 2 | branch<name> |
Always (or branchdetached) |
| 3 | commits<N> |
Always |
| 4 | sha<hex> |
Always (7-40 chars) |
| 5 | dirty |
Worktree dirty |
Whether metadata appears in the rendered string depends on the Show instance.
Tag Recognition
Commit Scanning
Scope
| Condition | Scan Range |
|---|---|
| Base tag exists | Commits after base up to HEAD |
| No base tag | All commits reachable from HEAD |
Traversal
- All commits are scanned, including merge commits themselves
- Keywords scanned from all reachable paths (traverses entire merge graph)
- Commit count for metadata uses first-parent only, excluding merges
Ignore Directives
Commits can be excluded from version calculation:
| Directive | Effect |
|---|---|
version: ignore |
Excludes the commit containing this directive |
version: ignore: <sha> |
Excludes specific commits by SHA prefix |
version: ignore: <a>..<b> |
Excludes commits in the range (inclusive) |
version: ignore-merged |
Excludes all commits from the merged branch |
Use case: When merging a PR, use version: ignore-merged in the merge commit to discard all incoming version directives and specify a consolidated directive instead.
Examples
| Scenario | Base | Result |
|---|---|---|
Tagged v2.3.1, clean |
— | 2.3.1 |
| No keywords | 1.4.5 (final) |
1.4.6-SNAPSHOT+... |
target: 2.0.0 |
1.9.0 |
2.0.0-SNAPSHOT+... |
breaking: API change |
1.0.0 |
2.0.0-SNAPSHOT+... |
| No keywords | 3.0.0-rc.3 |
3.0.0-SNAPSHOT+... |
| No tags in repo | — | 0.1.0-SNAPSHOT+... |
In this article