In short: jj takes either exact name@remote symbols or name patterns, optionally limited
with --remote (default: every remote except the reserved git). It collects the
matching remote bookmarks, including not-yet-existing ones for local bookmarks on a remote, and skips
those already tracked with a warning. In one transaction it calls track_remote_bookmark on
each: a three-way merge of the remote target into the local bookmark, then the state is set to tracked.
It records track remote bookmark <symbols> and lists any bookmark left conflicted.
The command is cmd_bookmark_track. Its inverse is
jj bookmark untrack. Bookmarks
can also become tracked automatically on fetch through remotes.<name>.auto-track-bookmarks
(see git fetch). How
RemoteRef stores the tracking state is on the view
page.
1. Command-line surface
| Argument | Type | Default | Meaning |
|---|---|---|---|
BOOKMARK[@REMOTE] (positional) | patterns or remote symbols, required | — | Either name patterns (globs by default) or exact name@remote symbols, but not both in one call (source, parse_name_patterns_or_remote_symbols). |
--remote REMOTE | remote patterns, repeatable | all remotes but git | Which remotes the name patterns apply to. Not allowed with name@remote symbols (source). |
2. Configuration
templates.bookmark_list formats the listing of bookmarks left conflicted
(source). In a Git-backed repo the reserved git remote
is excluded from pattern matches unless --remote names it
(source, default_ignored_remote_name).
3. End-to-end flow
4. Core architecture touchpoints
| Structure | Read / write | How | Explained on |
|---|---|---|---|
RemoteRef.state | write | Set to Tracked. An absent remote bookmark can be tracked too, which is how a local bookmark gets ready to be pushed to a new remote (source). | view |
View.local_bookmarks | write | Three-way merged with the remote target; created if absent, conflicted if both sides differ (merge_local_bookmark). | view |
| Index | read | Ancestry, used by merge_ref_targets to resolve the merge. | index |
| Commits | untouched | A new local bookmark adds its target as a head if needed. | commits |
| Operation | write | One operation if anything was tracked; otherwise Nothing changed. | operations |
5. Transaction and operation
- Transaction: always started; when nothing was selected,
tx.finishfinds no changes and printsNothing changed.(source, test). - Operation description:
track remote bookmark <name@remote, …>(source). - Commits: none created or rewritten.
jj undorestores the previous local target and tracking state.
6. Algorithm and invariants
Selecting remote bookmarks
With name@remote symbols, each is accepted if the remote bookmark exists, or if a local
bookmark of that name exists and the remote is known; others are reported with
No matching remote bookmarks for names (source).
With patterns, jj takes every existing remote bookmark matching both name and remote patterns, plus, for
every matching remote, an absent placeholder for each matching local bookmark the remote doesn't have
(source). Mixing the two forms is rejected because a
--remote or default would apply to only half the arguments (source).
Tracking is a merge
track_remote_bookmark merges with base
tracked_target(), which is absent for an untracked ref
(source), and other = the remote target. So:
- No local bookmark: the local bookmark is created at the remote target.
- Local bookmark at the same commit: unchanged.
- Local bookmark elsewhere: the result is a conflicted bookmark with both targets, which jj then lists.
Invariants: tracking never moves the remote target. A tracked remote bookmark and the local bookmark of the same name are thereafter treated as one: fetches merge remote changes into the local bookmark, and pushes use the tracked target as the expected remote state.
7. Errors and edge cases
| Message | When | Source |
|---|---|---|
Cannot specify both <bookmark> patterns and <bookmark>@<remote> symbols | Mixed argument forms (exit status 2). | track.rs |
--remote cannot be used with <bookmark>@<remote> symbols | Both given. | track.rs |
Warning: Remote bookmark already tracked: <symbol> | Skipped; not an error. | track.rs |
Warning: No matching remote bookmarks for names: … | A symbol names nothing trackable. | mod.rs |
Warning: No matching bookmarks for names: … / No matching remotes for names: … | Exact names or remotes that don't exist. | mod.rs |
Nothing changed. | Nothing new to track. | cli_util.rs |
8. Worked example
From upstream's test_bookmark_track_untrack. A fetch without
auto-tracking leaves feature1@origin, feature2@origin and main@origin
untracked, all at commit 1, with no local bookmarks. Then
jj bookmark track feature1@origin main@origin nonexistent@origin, and later, after creating a
local feature2 at @, jj bookmark track feature2:
Upstream's output for the first call (source):
Warning: No matching remote bookmarks for names: nonexistent@origin
Started tracking 2 remote bookmarks.
jj bookmark track feature3 --remote=origin, for a name that exists nowhere, prints
Warning: No matching bookmarks for names: feature3 and Nothing changed.