Mental Model: Working Copy as a Commit
The biggest difference between git and jj is how they think about your working copy.
In git: Three States
Git has three separate states for your code:
- Working copy - Your actual files on disk
- Staging area - Changes ready to commit
- Repository - Committed snapshots
# git workflow
git status # Check working copy
git add file # Move to staging
git commit # Move to repository
In jj: Two States
jj combines the working copy and the repository. Your working copy is a commit.
- Working copy - Represented by the
@commit - Repository - All other commits
# jj workflow
jj status # Check the @ commit
jj describe # Name the @ commit
jj new # Create a new @ commit
The @ Commit
In jj, your uncommitted changes are represented by the @ commit. It's a real commit that exists in the repository.
git statusgit diff src/app.tsjj statusjj show @| git | jj |
|---|---|
| git status | jj status |
| git diff src/app.ts | jj show @ |
No Staging Area
Since your working copy is already a commit, there's no staging area.
git add app.tsgit add test.tsgit commit -m "Fix bug"jj describe -m "Fix bug"jj new| git | jj |
|---|---|
| git add app.ts | jj describe -m "Fix bug" |
| git add test.ts | jj new |
| git commit -m "Fix bug" |
In jj, all file changes are automatically tracked. There's no need to jj add files—your changes are already part of the @ commit.
Practical Example
Let's say you're working on a feature and want to commit your changes.
vim src/app.tsgit statusgit add src/app.tsgit commit -m "Add feature"vim src/app.tsjj statusjj describe -m "Add feature"jj new| Git workflow | jj workflow |
|---|---|
| vim src/app.ts | vim src/app.ts |
| git status | jj status |
| git add src/app.ts | jj describe -m "Add feature" |
| git commit -m "Add feature" | jj new |
Why This Matters
The @ commit model enables several jj features:
- Instant undo -
jj op undoreverses any operation - Edit old commits - No separate "staging" to conflict with
- Automatic rebasing - Clear lineage between commits
- First-class conflicts - Conflicts live in commits, not separate files
Visualization
[Working Copy] → [Staging] → [Repository][@ Commit] → [Repository]| Git state | jj state |
|---|---|
| [Working Copy] → [Staging] → [Repository] | [@ Commit] → [Repository] |
Try It Yourself
Explore the @ commit:
# Show the current @ commit
jj show @
# Show changes in @
jj diff
# Rename the @ commit
jj describe -m "Working on feature"
# See all commits including @
jj log
Key Takeaways
- Your working copy in jj is the
@commit - No staging area—all changes are auto-tracked
jj describenames the@commitjj newfinalizes@and creates a new one
Next Steps
Now that you understand the mental model, let's look at creating your first commits in jj.