jj / How jj workspace rename works

How jj workspace rename works

jj workspace rename gives the current workspace a new name. The name is stored in three places, the repo's view, the workspace's own working-copy state, and the workspace store, and the command changes all three together.

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 refuses an empty name, does nothing if the name is unchanged, and refuses if the current workspace isn't in the view. It then starts a transaction, locks the working copy, renames the workspace in the working-copy state, in the view (which moves its working-copy commit and Git HEAD to the new name, refusing a name that's taken) and in the workspace store, commits the operation Renamed workspace '<old>' to '<new>', and records it in the working copy.

The command is cmd_workspace_rename. It can only rename the workspace it runs in. Workspaces are created by jj workspace add; the name is what NAME@ means in revsets and jj log.

1. Command-line surface

ArgumentTypeDefaultMeaning
NEW_WORKSPACE_NAME (positional)workspace namerequiredThe new name for the current workspace (source).

2. Configuration

None. The name has no config of its own.

3. End-to-end flow

jj workspace rename: call flow cmd_workspace_rename refuses an empty name, loads the workspace, prints Nothing changed if the name is the same, and refuses if the current workspace isn't in the view. It starts a raw transaction and locks the working copy, then renames the workspace in the working-copy state, the view and the workspace store. The transaction is committed as Renamed workspace, and the working-copy lock is released at the new operation. empty → error; same name → "Nothing changed." current workspace not in the view → error start a transaction; lock the working copy (start_working_copy_mutation) working-copy state locked_wc.rename_workspace view wc commit ID and Git HEAD move to the new name workspace store rename the entry tx.commit("Renamed workspace 'OLD' to 'NEW'") locked_ws.finish(new op ID): the working copy now records the new operation

The old name is read from the working copy itself, not from command arguments (source), which is why a forgotten workspace can't be renamed back into the repo: its working copy still has its name, but the view doesn't (test).

4. Core architecture touchpoints

  • View: View::rename_workspace moves the working-copy commit ID and, if recorded, the Git HEAD from the old name to the new one, through MutableRepo::rename_workspace. See the view page.
  • Working copy: the working-copy state stores its workspace name, so it is renamed under the working-copy lock; see the working copy page.
  • Workspace store: the entry's name changes and its path stays (rename), so jj workspace root --name NEW works and the old name no longer does (test).
  • Commits: none change; jj log shows NEW@ on the same commit.

5. Transaction and operation

  • Transaction: a raw one (into_inner), committed directly rather than through finish, because the working copy is updated by hand: the lock is taken before the view changes and released with the new operation ID (source).
  • Operation description: Renamed workspace '<old>' to '<new>', unusually capitalized and in the past tense compared to other commands (source).
  • Outside the operation: the workspace store rename and the working-copy state are written to disk directly, not recorded in the operation.

6. Algorithm and invariants

The three places a workspace name lives, before and after rename Before: the view maps second to commit 94f41578, the working-copy state of the secondary directory says second, and the workspace store maps second to ../secondary. After jj workspace rename third, all three say third, with the same commit and path. before after rename third view: second → 94f41578 view: third → 94f41578 secondary/.jj/working_copy: second secondary/.jj/working_copy: third workspace store: second → ../secondary workspace store: third → ../secondary

Invariants: names stay unique in the view; no commit changes; the workspace's directory and working-copy commit are the same before and after.

7. Errors and edge cases

MessageWhenSource
New workspace name cannot be emptyAn empty name.rename.rs, test
Nothing changed.The new name equals the current one.rename.rs, test
The current workspace '<name>' is not tracked in the repo.The workspace was forgotten.rename.rs, test
Failed to rename a workspace, caused by Workspace <name> already existsAnother workspace has that name.view.rs, test

8. Worked example

From upstream's test_workspaces_rename_workspace. With workspaces default and second (in ../secondary), running jj workspace rename third in the secondary directory prints nothing. Afterwards (source):

$ jj workspace list
default: . qpvuntsm e8849ae1 (empty) (no description set)
third: ../secondary uuqppmxq 94f41578 (empty) (no description set)

$ jj log    # from the secondary directory
@  94f41578a9e1 third@
│ ○  e8849ae12c70 default@
├─╯
◆  000000000000

The commit IDs and the directory are unchanged; only the name moved, in all three places shown in §6.