jj
a version control system
2026-03-27
aboutπ
A couple months ago I was jj curious, and started a new job, and took advantage of the change to start using it full time. I have pretty much not used git directly since!
This is the prose article version of the slides I just presented to my team to give them a ~5 minute lightning talk style introduction to jj.
what is gitπ
(link to https://xkcd.com/1597)
you know git
famously poor ux
- changing branches midstream is hard: stash / stash pop / βwipβ commit
- overloaded checkout: new branch, switch branch, restore file?
- rebases are painful; conflict resolution is painful
- detached head state???? what even is this
POLL: how many people actually use git by typing commands into the terminal? as opposed to having AI or an IDE do it for you?
what is jjπ
- version control system
- uses git for a backend
- seamlessly integrated
- iβve secretly been using jj for almost six months now!
you donβt know jj but maybe you want to!
why shoud i careπ
- great ux
- more simple
- more powerful
howπ
- π« staging area π«
- (every change is auto-committed)
- rebases always succeed
- anonymous branches
- auto-commit is awesome
- no more having to remember.. git rebase βcontinue? or, git add; git commit?
- bookmarks (tags) over branches
- moving back and forth is effortless
- in practice you just start committing on main and itβs fine
- itβs just soooo much easier to jump around and perform edits anywhere and everywhere. no changing branches, no interactive rebases to edit history. you just β¦ make edits.
changes vs commitsπ
@ kzkvzsyq chris.brown@guild.com 2026-02-24 12:08:30 ee1ce7f0
β docs: code promotion
β β rozumxpm travis.rivers@guildeducation.com 2026-03-26 15:24:31 PATH-3862-semantic-search 5d7f958d
β β test: seed webpack config env vars
β β owsloxzt travis.rivers@guildeducation.com 2026-03-26 14:39:31 413bd03d
β β Update catalog API URL default
β β nlwrxosv travis.rivers@guildeducation.com 2026-03-26 14:01:58 16a10043
β β style: format semantic search guard
β β srxlzzoq travis.rivers@guildeducation.com 2026-03-26 14:01:06 626f3b7c
β β fix: gate semantic search hydration behind wave 3
β β uwmnulzm travis.rivers@guildeducation.com 2026-03-26 14:00:59 7c22f7c3
β β fix: gate semantic search behind wave 3
β β vuxonmvt 45524041+travrivers@users.noreply.github.com 2026-03-26 13:11:15 fix/catalog-api-url-default main d2ba9ac1
β β Fix Wave 3 funding filter result/count consistency (#2251)
- change ids are immutable
- commit ids change all the time; we donβt care about them
- you can edit any change any time; no rebasing weirdness
workflowπ
jj new main- (do stuff)
jj desc- repeat
also supports a squash workflow: https://steveklabnik.github.io/jujutsu-tutorial/real-world-workflows/the-squash-workflow.html
oh shit gitπ
ohshitgit is a collection of common git problems and their solutions
this is a fun way to do a side-by-side comparison because it reveals that a lot of common git problems simply do not exist with jj
Oh shit, I did something terribly wrong, please tell me git has a magic time machine!?!π
GIT
git reflog
## you will see a list of every thing you've
## done in git, across all branches!
## each one has an index HEAD@{index}
## find the one before you broke everything
git reset HEAD@{index}
JJ
jj op undo
global undo is sick. undo rebases, merges, anything
Oh shit, I committed and immediately realized I need to make one small change!π
GIT
## make your change
git add . # or add individual files
git commit --amend --no-edit
JJ
...just edit the file
this problem does not exist in jj
Oh shit, I need to change the message on my last commit!π
GIT
git commit --amend
## follow prompts to change the commit message
JJ
## describe ANY change:
jj desc abc
I think to edit a message from long ago, you have to
e.g. git rebase -i HEAD~5 and then βrewordβ ? with jj you
can edit any description any time from anywhere
Oh shit, I accidentally committed something to master that should have been on a brand new branch!π
GIT
## create a new branch from the current state of master
git branch some-new-branch-name
## remove the last commit from the master branch
git reset HEAD~ --hard
git checkout some-new-branch-name
## your commit lives in this branch now :)
JJ
## n/a
## or, move the commit somewhere else:
jj rebase -r abc -d def
not really a thing in jj because of anonymous branches. you just work on master anyway, and then update your bookmark
Oh shit, I accidentally committed to the wrong branch!π
GIT
# undo the last commit, but leave the changes available
git reset HEAD~ --soft
git stash
# move to the correct branch
git checkout name-of-the-correct-branch
git stash pop
git add . # or add individual files
git commit -m "your message here";
# now your changes are on the correct branch
JJ
jj rebase -r abc -d def
only kind of a thing in jj. if you need to move / cherrypick / whatever a change, then just move it.
Oh shit, I tried to run a diff but nothing happened?!π
GIT
git diff --staged
JJ
n/a
no staging area
problem does not exist in jj
Oh shit, I need to undo a commit from like 5 commits ago!π
GIT
# find the commit you need to undo
git log
# use the arrow keys to scroll up and down in history
# once you've found your commit, save the hash
git revert [saved hash]
# git will create a new commit that undoes that commit
# follow prompts to edit the commit message
# or just save and commit
JJ
jj abandon abc
you can always abandon any change. it automatically rebases the changeβs descendantβs onto the parent
Oh shit, I need to undo my changes to a file!π
GIT
# find a hash for a commit before the file was changed
git log
# use the arrow keys to scroll up and down in history
# once you've found your commit, save the hash
git checkout [saved hash] -- path/to/file
# the old version of the file will be in your index
git commit -m "Wow, you don't have to copy-paste to undo"
JJ
jj restore --from abc path/to/file
demoπ
so what does it look like
quick demo of:
- anonymous branches
- cherry picking
- make a bookmark
consπ
- learning curve
- (but exists alongside git, so you can just use git if youβre stuck)
- itβs so easy to rewrite history, you end up changing history and having to force push changes
- bookmark management isnβt 100% ergonomic
- you eventually start to forget git?
getting startedπ
brew install jj
jj help -k tutorialyou really start to notice the pain points of git and how much awkwardness we just accept once you experience how easy jj is
- everything you can do in git you can do in jj:
- squashes
- splits
- claude can use it just fine: just add a few lines to CLAUDE.md