Install jj and Clone Your First Repo

Lesson 2 · jj for Git Users · ~8 minutes

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.

1. Install jj

On macOS with Homebrew, it's one command:

brew install jj

Verify it worked:

$ jj --version
jj 0.28.2
Version note

Your version number will vary. jj releases frequently. Anything 0.20+ will work for this course.

2. Configure Your Identity

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"
Different emails per project?

Drop --user and run from within a repo to set per-repo config, stored in .jj/repo/config.toml.

3. Two Ways to Start: Clone vs. Colocate

jj gives you two entry points depending on your situation:

Fresh Clone

# 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.

Colocated (existing repo)

# 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.

Which should you pick?

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.

4. Clone a Repo

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:

5. Explore: jj status and jj log

jj status

$ 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

$ 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:

git log

$ 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

$ jj log
@  kpqvuntx ... (empty)
◆  zmmrxslq ... main
◆  tpstlust ...

Shows commits including your in-progress working copy at the top.

The @ symbol

@ 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."

6. Colocated Mode In Depth

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:

my-existing-project/ ├── .git/ ← git's data (unchanged) ├── .jj/ ← jj's data (new) ├── src/ ├── README.md └── ...

What this means in practice:

One thing to watch in colocated mode

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.

The Escape Hatch

Colocated mode is perfect for evaluation because:

  1. You keep your existing git remote setup, hooks, and CI integration.
  2. Teammates who don't use jj never know you're using it — you push via git.
  3. If jj doesn't click, delete .jj/ and nothing has changed.

Quick Reference

StepCommand
Installbrew install jj
Configure identityjj config set --user user.name "..."
jj config set --user user.email "..."
Clone freshjj git clone <url>
Colocate existingjj git init --colocate (inside a git repo)
Check statejj status
See historyjj log

Check Your Understanding

What does "colocated mode" mean in jj?
Correct — colocated mode means .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.
Not quite. Colocated mode means .jj lives alongside .git in the same directory — both tools work on the same repo, and you can remove .jj at any time to go back to pure git.
In jj log output, what does the @ symbol refer to?
Right — the @ 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."
Not quite. The @ symbol always refers to the working-copy commit — the single commit you are currently editing. It's jj's equivalent of "where you are right now."
What happens if you remove the .jj directory from a colocated repo?
Exactly — since colocated mode keeps .git intact, removing .jj simply takes jj out of the picture. Your git repo continues working as if jj was never there. All commits are preserved in git's storage.
Not quite. Since colocated mode keeps .git intact, removing .jj simply takes jj out of the picture. Your git repo continues working as if jj was never there — all history is preserved in git's storage.
Primary Source

Installation & Setup — Official jj Docs — the canonical guide for installing jj, configuring identity, and initializing repos.

Questions? Stuck on installation? Unsure whether to use colocated mode or a fresh clone for your situation? Want to understand what's inside the .jj directory? Ask me anything.
← Prev Next →