jj / How jj tag delete works

How jj tag delete works

jj tag delete removes local tags matching name patterns. The commits they pointed to are kept, and become mutable again unless something else keeps them immutable.

On this page
  1. 1. Command-line surface
  2. 2. Configuration
  3. 3. End-to-end flow
  4. 4. Core architecture touchpoints
  5. 5. Transaction and operation
  6. 6. Algorithm and invariants
  7. 7. Errors and edge cases
  8. 8. Worked example

In short: jj matches the patterns against local tags, warns about exact names that don't exist, and prints No tags to delete. if nothing matched. Otherwise, in one transaction, it sets each matched tag's target to absent, prints Deleted N tags., and records delete tag <names>.

The command is cmd_tag_delete, also available as jj tag d (source). It is the tag counterpart of jj bookmark delete; to create or move tags, see jj tag set.

1. Command-line surface

ArgumentTypeDefaultMeaning
NAMES (positional)name patterns, required—Tags to delete; globs by default, other string-pattern kinds allowed, several unioned (source, parse_union_name_patterns).

TagDeleteArgs

2. Configuration

None of its own. Because the default immutable_heads() includes tags(), deleting a tag can make its commit mutable again (source). In a colocated workspace the deletion is exported to Git.

3. End-to-end flow

jj tag delete: call flow cmd_tag_delete loads the workspace, parses the name patterns, and collects matching local tags, warning about exact names without one. With no matches it prints No tags to delete. Otherwise a transaction sets each matched tag to absent, prints Deleted N tags, and tx.finish records delete tag. Shared lifecycle: load workspace and repo, snapshot the working copy (CLI page) union of name patterns → local_tags_matching; warn on exact names with no local tag no matches → "No tags to delete." set_local_tag_target(name, absent) for each "Deleted N tags." tx.finish(ui, "delete tag <names>") colocated: exported to Git

4. Core architecture touchpoints

StructureRead / writeHowExplained on
View.local_tagswriteEach match is removed. Remote tag entries that are absent are dropped with it; present ones stay (source).view
Immutable setchangesThe commit leaves tags(), so it may become mutable.revsets
CommitsuntouchedNothing is abandoned.commits
OperationwriteOne operation if anything matched.operations

5. Transaction and operation

  • Transaction: one, only when something matched (source).
  • Operation description: delete tag <name1, name2, …> (source).
  • Commits: none created or rewritten.
  • jj undo brings the tags back.

6. Algorithm and invariants

The patterns are unioned and matched against local tags only (source). A tag matched by several patterns is deleted once. The unmatched warning covers only exact names (warn_unmatched_local_tags), so unknown* just prints No tags to delete. Removing a tag goes through set_local_tag_target(name, absent).

Invariants: only local tag entries change; commits and present remote tags are untouched. All matches are deleted, or none.

7. Errors and edge cases

MessageWhenSource
No tags to delete.No local tag matched.delete.rs
Warning: No matching tags for names: …An exact name has no local tag.mod.rs, test
Failed to parse name pattern: …A pattern doesn't parse.revset_util.rs
clap: missing <NAMES>No names given.delete.rs

8. Worked example

From upstream's test_tag_set_delete, at the end of the test: bar is on commit1, and baz has just been moved to the commit above bbc74930. Then jj tag delete 'b*':

jj tag delete b* and immutability Before: b876c5f4 has tag bar, bbc74930 has no tag, 13cbd515 has tag baz, and @ cca3d7af is on top; the tagged commits and their ancestors are immutable. After deleting b*, both tags are gone and the three commits, no longer reachable from any tag, are shown as mutable. before (◆ = immutable) after jj tag delete 'b*' root b876c5f4 bar bbc74930 13cbd515 baz cca3d7af @ root b876c5f4 bbc74930 13cbd515 cca3d7af @

Upstream's output and log (source):

Deleted 2 tags.
@  cca3d7af9d98
○  13cbd51558a6
○  bbc749308d7f
○  b876c5f49546
◆  000000000000

In the log, ◆ marks immutable commits: with the tags gone, the three commits are drawn as ordinary mutable ones.