From zero to a working jj-managed repo in five minutes. You'll install jj, configure your identity, and clone a repository — learning how jj presents its commit graph along the way.
On macOS with Homebrew, it's one command:
brew install jj
Verify it worked:
$ jj --version
jj 0.28.2
Your version number will vary. jj releases frequently. Anything 0.20+ will work for this course.
jj needs your name and email for commit authorship, just like git:
jj config set --user user.name "Your Name"
jj config set --user user.email "you@example.com"
The --user flag stores these in your global config (~/.jjconfig.toml), so you only do this once. Verify with:
$ jj config list user
user.email = "you@example.com"
user.name = "Your Name"
Drop --user and run from within a repo to set per-repo config, stored in .jj/repo/config.toml.
jj gives you two entry points depending on your situation:
# Clone from a remote
jj git clone <url> [dest]
Creates a jj-native repo. The .git directory exists inside .jj/ as a storage backend. You interact exclusively through jj.
# Inside an existing git repo
cd my-git-repo
jj git init --colocate
Creates a .jj/ directory alongside your existing .git/. Both jj and git commands continue to work on the same repo.
For evaluating jj, colocated mode is the safe choice. Your existing git workflow still works — you can fall back to git any time. Use jj git clone when you're ready to go all-in on a project.
Let's clone one of your GitHub repos. Pick something small you're comfortable experimenting with:
$ jj git clone git@github.com:yourname/your-repo.git
Fetching into new repo in "/Users/you/your-repo"
Working copy now at: kpqvuntx 4a8b3f2d (empty) (no description set)
Parent commit : zmmrxslq 9f1c7e3a main | latest commit message here
Added 42 files, modified 0 files, removed 0 files
That output tells you several things at once:
$ jj status
The working copy is clean
Working copy : kpqvuntx 4a8b3f2d (empty) (no description set)
Parent commit: zmmrxslq 9f1c7e3a main | latest commit message here
Unlike git status, this always shows you which commit you're editing and its parent. There's no ambiguity about "where you are."
$ jj log
@ kpqvuntx you@example.com 2025-07-01 08:30:00 4a8b3f2d
│ (empty) (no description set)
◆ zmmrxslq you@example.com 2025-06-30 14:22:00 main 9f1c7e3a
│ latest commit message here
◆ tpstlust you@example.com 2025-06-28 09:15:00 7b2e4c1f
│ previous commit message
~
Key things to notice:
@ — marks the working-copy commit. This is jj's equivalent of HEAD, but simpler: it always points at exactly one commit, and that commit is what you're currently editing.◆ — immutable commits (already pushed or otherwise protected). You can't accidentally edit these.kpqvuntx) — these short prefixes are stable across rewrites. You'll use them constantly.4a8b3f2d) — these are the familiar SHA hashes. They change when a commit is rewritten; change IDs don't.$ git log --oneline -3
9f1c7e3 latest commit message
7b2e4c1 previous commit
a3d8f12 third commit back
Shows committed history. Working directory state is invisible.
$ jj log
@ kpqvuntx ... (empty)
◆ zmmrxslq ... main
◆ tpstlust ...
Shows commits including your in-progress working copy at the top.
@ is the revset symbol for "the current working-copy commit." You can use it in any command: jj show @, jj diff @, jj rebase -r @ -d main. It always means "the commit I'm editing right now."
If you have an existing git repo you'd rather not re-clone, colocated mode lets you layer jj on top:
$ cd ~/my-existing-project
$ jj git init --colocate
Done importing changes from the underlying Git repo.
Working copy now at: rlvkpntz 8c4f2a1b (empty) (no description set)
Parent commit : qpvuntsw e7a3d5c9 main | some commit message
Added 0 files, modified 0 files, removed 0 files
After this, your directory has both:
What this means in practice:
git status, git push, git log all function normally.jj status afterward to let jj pick up the changes.rm -rf .jj and you're back to plain git. Nothing is lost.If you make changes with git (e.g., git commit), jj will notice them next time you run a jj command. But if both tools are mid-operation simultaneously, you can get confused. Stick to one tool at a time for any given editing session.
Colocated mode is perfect for evaluation because:
.jj/ and nothing has changed.| Step | Command |
|---|---|
| Install | brew install jj |
| Configure identity | jj config set --user user.name "..."jj config set --user user.email "..." |
| Clone fresh | jj git clone <url> |
| Colocate existing | jj git init --colocate (inside a git repo) |
| Check state | jj status |
| See history | jj log |
.jj lives alongside .git in the same directory. Both jj and git commands work on the same repo, and you can remove .jj at any time to go back to pure git.@ symbol refer to?@ symbol always refers to the working-copy commit. It's the single commit you're currently editing — jj's equivalent of "where you are right now.".jj directory from a colocated repo?Installation & Setup — Official jj Docs — the canonical guide for installing jj, configuring identity, and initializing repos.