The working copy is a commit, and other things that took a moment to click

Part 3 of 9.

Git’s mental model has three layers: working directory, index (staging area), and commits. Most of the day-to-day friction I associate with Git - git add -p, forgetting to stage a file, git status showing overlapping “staged” and “unstaged” sections for the same file - comes from managing the boundary between the first two.

jj removes that boundary. The working directory is the content of a real commit, addressed as @. Every command snapshots it first. There’s no jj add. Wanting to commit “some but not all” of the current changes is handled by jj split, which is an explicit act on the commit itself rather than a running side-negotiation with an index.

Once that clicked, two more ideas fell into place quickly:

Two ids per commit, not one. The change id (qpvuntsm) identifies “this piece of work” and stays constant across edits and rebases. The commit id (230dd059) is a content hash, exactly like a Git SHA, and changes whenever the content does. Referring to work by change id means the reference survives being rewritten - genuinely useful once lesson 5’s jj edit and jj new-on-the-past become normal moves rather than special cases.

The operation log is not the reflog. git reflog tracks where branches and HEAD pointed. jj op log tracks every operation that changed anything about the repository - rebases, describes, config changes made through jj config set, all of it. jj undo reverses the last one; jj op restore <id> jumps back to any earlier point. I tested this by deliberately describing a commit wrong and then undoing it, and it did exactly what it says, no reflog archaeology required.

The one restriction worth internalizing early: commits at or behind trunk(), or already pushed to a tracked remote bookmark, are immutable by default. Trying to edit one gets a refusal with an explanation, not a rewritten shared history by accident. It’s the same “don’t rebase what you’ve pushed” convention Git relies on people remembering, except jj actually enforces it.