JJ has replaced git for me
`jj new post`

Photo taken inside the Mosque-Cathedral of Cordoba
Git is a good tool. It's fast and and reliable. It's been around for over 20 years for a reason.
I don't mind git. I wouldn't say I enjoy using it; I can usually get it to do what I want. When things get messy, I chant an incantation of different commands and SHA's and everything's back on track.
While I feel competent with git, it sometimes feels like a chore to use. Every git user has a bunch of git aliases in their shell. At this point, I wouldn't mind an abstraction on top – some CLI tool or GUI. But I also dislike it when I don't know how to use the abstraction or when it breaks. If I feel like it's getting in the way, I'd want the option of rolling up my sleeves and dropping back down to plain git.
This is why I love Jujutsu (JJ). It's is designed to support different backends, such as git (the only one today). You can also use git and jj at the same time, in the same repository.
jj vs git
If you want a pull request to ship quickly, you'll put in effort to make sure it can be reviewed quickly – not the topic of this post – but when you're doing so, you'll probably perform one or more of these manoeuvres:
I'll assume you know how to do this in git, and I'll show you how to do it in jj. But first, I should probably explain how to make a commit in jj.
how to make a commit in jj
In jj, there's no staging area - you're always editing a "commit". When you want to start a new one, you do:
Whenever you amend a commit, the SHA changes. This is also true for git. But in jj, every commit also has a stable change ID.
6b2ba360
is the current commit ID and skoknytr
is the change ID. Watch what happens when we reword the commit:
The commit ID was updated, but not the change ID. This is one of the advantages jj has over git: it can keep track of commits even when you amend them.
Let's look at more!
Reordering commits
The git incantation I'd use here is git rebase -i HEAD~n
which gives me an overview of past commits. The big drawback is that this would rewrite commits in history up to n
even when left untouched, so I need to be careful not to rewrite a commit I already pushed to the remote.
With jj, this is much simpler (this is going to be the theme). Let's say we have the following tree
and we'd like to reorder mwnlowpn
and rltznoyl
to appear before skoknytr
Notice how we only had to specify the highlighted prefix of the change ID to reference it? That's because unlike git, jj doesn't hate you1.
Squashing a commit
You're iterating on a change, you made an edit that should have been in an earlier commit, more than one commit back. How do we get it there?
With git, I'd make a temporary commit and use git rebase -i
to apply the fixup marker. In jj, the squash
command takes in a revision or even a file path.
And in interactive mode -i
, you could also select hunks.
Rebasing a stack
The working model is quite similar to how you'd do this in git, but the management aspect is far more pleasant.
Here's a stack of 2 branches. In jj, branches are called bookmarks. They're not exactly the same as git branches, but you can think about them and work with them in the same ways. When you push a bookmark to the remote origin, the git backend creates a git branch.
There's also a parallel change ylxytysw
that's based on the same revision as our stack, skoknytr
. This could be a commit that landed in main
while we're working on our changes or our own merge commit for one of the earlier branches in our stack.
When I'm faced with this in git, I reach for an advanced command git rebase --onto
2 to avoid dealing with conflicts. It's a big time save, but it's still only capable of rebasing one branch at a time.
What we're doing here is moving a connected range of commits to come after a particular commit. The jj version is as simple as that sentence.
I haven't even shown you jj split
or jj op
- there's a ton more about jj that makes it a joy to use.
If you're intrigued, check out the docs. There are many (lengthy) tutorials in the wild. But honestly, you can just dive into it. jj new
, jj bookmark set [name]
and jj git push
is all you need in the beginning. Oh and if you use the built-in merge tool, this cheatsheet will be handy.