About Nielsen Ramon header image

<- teaching-jj

Jujutsu is the GOAT but I have no idea how to teach people about it

jj is the best version control system I've used, but teaching it to students new to VCS is a surprisingly hard problem.

Oh look another nerd deciding to waste more internet bandwidth on all the wonderful virtues of Jujutsu VCS.

I'm not the first and I won't be the last. Here's a sampling of the discourse:

JJ is worth the hype however, it modernizes one of the most critical components of software engineering, bringing it into the 2020s. The developer experience scales naturally across many axes: small project just starting out <-> large project with tons of developers, local only development <-> multiple remotes moving independently, one user using JJ in a Git world <-> everyone being fully JJ pilled. It saves you from yourself. You can be much more brave about complex VCS operations like rebasing, squashing and cherry picking and the intermediate state tracking allows you to undo and redo operations to recover otherwise lost work. Bookmarks and commit ranges I believe are a superior abstraction to branches. My main complaint is conflict resolution is difficult to do by hand but nothing is perfect out of the box.

I think JJ is good enough that I'd love to introduce it to the students I teach. Maybe it might save them from the classic fresh developer issues like forgetting to push after committing or forgetting to stage commits before commiting or forgetting to pull or forgetting to switch branches, not pushing to master etc. etc. Git is great, in my day as an undergrad schools still used SVN, we clammored to use Git to avoid SVN's problems. The issue with Git is to use it right you need to have a strong mental model confidently navigate common operations and constant vigilance is required to make sure the repository doesn't spiral out of hand.

To use Git properly you need to hold this in your head at all times:

  Working Directory          Staging Area            Local Repo             Remote Repo
  (your files on disk)       (the index)             (.git/objects)         (GitHub etc.)

       │                          │                       │                      │
       │──── git add ────────────>│                       │                      │
       │                          │──── git commit ──────>│                      │
       │                          │                       │──── git push ───────>│
       │                                                  │<─── git fetch ───────│
       │<─────────────────── git checkout / restore ──────│                      │
       │<─────────────────────────────── git pull ────────────────────────────── │

Four distinct zones, eight commands to move between them, and the mental overhead of always knowing where your changes currently live. Miss a step anywhere — forget to git add, forget to git push, commit to the wrong branch — and you're debugging your VCS instead of writing code. For experienced developers this becomes muscle memory. For students who are simultaneously learning to code, it's a constant source of friction.

So that motivates the question: "What would it take to have students skip Git and go straight to JJ?"

What JJ Simplifies

The staging area is gone. The working copy is a commit — JJ automatically tracks every change you make as part of an ongoing, amendable commit. This collapses the four-zone model above into two: your working copy and the repo. The common newbie mistake of "I forgot to git add" simply does not exist.

jj undo and jj op log mean mistakes are recoverable. This is huge for beginners. In Git, "I accidentally reset my branch" or "I rebased wrong" can mean real data loss unless you know about the reflog. In JJ, the operation log tracks every action and you can undo them linearly. Students can be brave.

Revsets are a powerful query language for talking about commits. Instead of memorizing cryptic ref syntax (HEAD~3, origin/main..HEAD), you write readable expressions. This is a nice on-ramp to thinking about commit history as data you can query.

jj describe decouples writing your commit message from the act of snapshotting. You can work, then describe what you did. This maps more naturally to how beginners actually work — code first, explain later.

What JJ Doesn't Simplify

Because most code forges (GitHub, GitLab, Bitbucket) are Git-first, students still need to understand enough Git to operate in that world.

At minimum, a JJ-first curriculum still needs to cover:

ConceptWhy It Can't Be Skipped
CommitsThe fundamental unit — same in both
RemotesGitHub is a remote, this doesn't go away
fetch / pushStill how you sync with the forge
Bookmarks vs. BranchesPRs on GitHub are branch-based; JJ's bookmarks map onto this but the translation isn't obvious and confuses many people new to JJ

The bookmarks-to-branches translation is the hardest part. When a student wants to open a pull request on GitHub, they need to understand that their JJ bookmark becomes a Git branch becomes a PR. That's three layers of abstraction for someone who just wants to submit their homework. Also without the common tug alias, remembering to move your bookmarks and the exact way to do that can be tedious and easy to get incorrect, potentially poluting the upstream repo

What a JJ-First Curriculum Might Look Like

Level 0 — Just track changes locally: jj init, jj status, jj describe, jj log. No remotes, no branches, no pushing. Get comfortable with the idea that every save is being tracked and you can always go back.

Level 1 — Work with a remote: jj git clone, jj git fetch, jj git push. Introduce the concept of a remote as a mirror. Still no branches.

Level 2 — Collaborate: Bookmarks, how they map to Git branches, opening a PR. This is where the Git-forge translation layer gets introduced explicitly — "the rest of the world uses Git, here's how JJ talks to it."

Level 3 — Power tools: Revsets, jj rebase, jj split, jj absorb, jj op undo. The stuff that makes JJ genuinely better than Git for anyone doing non-trivial history management.

The Jujutsu for Everyone guide is structured similarly and is worth reading if you're thinking about this problem — they're actively building out exactly this kind of zero-prior-experience curriculum.

Open Questions

I don't have a clean answer yet. JJ's core model should be simpler than git if you didnt need to think about git and I believe it is more forgiving for new developers. But the forge ecosystem means you cannot fully escape Git concepts. The question is whether you're better off teaching Git as the foundation and JJ as an upgrade, or teaching JJ as the foundation and Git as a compatibility layer you'll sometimes need to think about.

My instinct is the latter. The mental model of "your working copy is always a commit, and you can always undo" is a healthier foundation than "here are four zones and eight commands."