In short: it is jj bookmark list over the
view's tags. The same collect_items groups each local tag with its tracked remote tags, the same
sort orders them, and each entry is rendered with templates.tag_list. Unlike the bookmark command it
prints no hints afterwards, and its unmatched-name warning only looks at local tags. It writes nothing.
The command is cmd_tag_list. The help text: "List tags and
their targets. By default, a tracked remote tag will be included only if its target is different from the local
tag. An untracked remote tag won't be listed" (source). It is registered as
List(TagListArgs) with the visible alias l (source,
dispatch).
1. Command-line surface
| Flag | Meaning |
|---|---|
NAMES (positional) | "Show tags whose local name matches", as glob patterns by default (source). |
-r, --revision REVSETS | "Show tags whose local targets are in the given revisions" (alias --revisions); "-r deleted_tag will not work" (source). The help suggests -r 'REV::' for tags on descendants of REV, "similar to git tag --contains REV", and -r '::REV' for ancestors, "similar to git tag --merged REV" (source). |
-a, --all-remotes | "Show all tracked and untracked remote tags including the ones whose targets are synchronized with the local tags" (alias --all) (source). |
--remote REMOTE | "Show all tracked and untracked remote tags belonging to this remote"; repeatable, glob by default, conflicts with -a (source). |
-t, --tracked | "Show tracked remote tags only. This omits local Git-tracking tags by default"; conflicts with -a (source). |
-c, --conflicted | "Show conflicted tags only"; conflicts with -a (source). |
-T, --template TEMPLATE | Render each entry with this template; all zero-argument methods of CommitRef are keywords (source). |
--sort SORT_KEY | Comma-delimited sort keys, the first most significant; a - suffix sorts descending (source). The same keys as jj bookmark list (source). |
The global flags are on the CLI page.
2. Configuration
| Setting | Default | Effect |
|---|---|---|
templates.tag_list | format_commit_ref(self, "tag") ++ "\n" | Each entry, labelled tag_list (default, source). format_commit_ref is described on the bookmark list page; here names carry the tag label. |
ui.tag-list-sort-keys | ["name"] | The sort keys when --sort is not given; it must be an array of key strings (default, source, parser). |
ui.pager | The command requests the pager (source). |
3. End-to-end flow
4. Core architecture touchpoints
| Piece | Role here |
|---|---|
View::tags | "Iterates pair of local and remote tags by tag name". See the view. |
collect_items | The grouping and filtering, identical to jj bookmark list. |
sort | Stable multi-key sort; loads commits only when a key needs them (details). |
CommitRef | The template type, with the keywords in builtin_commit_ref_methods. |
default_ignored_remote_name | The git pseudo-remote on the Git backend; --tracked leaves it out (source). |
5. What it reads, and snapshotting
It goes through workspace_helper, so the working copy is snapshotted first unless
--ignore-working-copy is given (source). It then reads the view's
tags, the commits the template prints, the revset evaluation for -r, and, for commit-based sort
keys, each group's first target commit (source). It starts no transaction
and writes no operation.
6. Algorithm and invariants
Which tags are listed
Names and revisions are OR-ed "like cmd_git_push()"; the revsets are intersected with
tags(all()) and matched against local targets only (source).
The predicates are set exactly as for bookmarks: local-only tags unless -t or --remote;
synced tracked remotes with -t, -a or --remote; untracked remotes with
-a or --remote but not -t (source).
The full table is on the bookmark list page.
The git pseudo-remote
In a colocated repository each tag also has a ref on the git remote, which is tracked. While it
agrees with the local tag it is hidden by default and shown by -a or --remote=git;
--tracked alone excludes it, so it printed nothing in upstream's test
(test). Remote tags from a real remote are tracked by default; see
jj tag track.
What is printed
Each group prints its primary ref and then its tracked remote refs, through the template
(source). With the default template a conflicted tag prints
(conflicted): with - and + lines for its removed and added targets,
(absent) for a term with no commit (source).
7. Errors and edge cases
| Situation | Behaviour |
|---|---|
| An exact name with no local tag | "Warning: No matching tags for names: …". Only local tags count, unlike jj bookmark list, which also accepts a remote one; glob patterns never warn (source, test). |
| A conflicted tag | Listed with its targets, with no hint (test). See jj tag set. |
| A deleted local tag still tracked on a remote | Listed as name (deleted) with its remote below, as for bookmarks, but no hint is printed (source). |
A conflicted tag and normal_target in a custom template | <Error: No value set to Option<Commit>>, as there is no single target (test). |
An unknown --sort key, or a bad ui.tag-list-sort-keys | Rejected by clap, or a config error such as "Expected an array of sort keys as strings" (source). |
-a with --remote, -t or -c | Rejected by clap (source). |
8. Example output
Three tags, one of them conflicted by concurrent operations, from upstream's test (source):
$ jj tag list
conflicted_tag (conflicted):
- rlvkpnrz 893e67dc (empty) commit1
+ zsuskuln 76abdd20 (empty) commit2
+ royxmykx 13c4e819 (empty) commit3
test_tag: rlvkpnrz 893e67dc (empty) commit1
test_tag2: zsuskuln 76abdd20 (empty) commit2
A revset and a name, which are not intersected (source), and newest first by committer date (source):
$ jj tag list -r 'subject(commit1)' test_tag2
test_tag: rlvkpnrz 893e67dc (empty) commit1
test_tag2: zsuskuln 76abdd20 (empty) commit2
$ jj tag list --sort=committer-date-,name
conflicted_tag (conflicted):
- rlvkpnrz 893e67dc (empty) commit1
+ zsuskuln 76abdd20 (empty) commit2
+ royxmykx 13c4e819 (empty) commit3
test_tag2: zsuskuln 76abdd20 (empty) commit2
test_tag: rlvkpnrz 893e67dc (empty) commit1
In a colocated repository, --all-remotes shows the git pseudo-remote
(source):
$ jj tag list --all-remotes
local-only: rlvkpnrz d3e8d245 (empty) local-only
@git: rlvkpnrz d3e8d245 (empty) local-only
See also jj tag set and jj tag delete.