JJ - A Better Git
I came across a tool that solved a problem I had, but I didn’t know anybody else also had, so was a bit surprised when I found it had been solved. I’m talking of jj, which I’ve been recently been giving a whirl as a frontend for Git.
This is not a tutorial. I’ll describe the problem, and how jj solves it. Then I’ll leave you with some links should this interest you.
I like Git. For me, it serves not just as a means of preserving and sharing code, but also as a way of thinking about changes. Such an approach is not always correct — many seedlings have been stifled by being caged in a git repository before they unfurled their first green — but once the plant is big enough, having it live in a git repository is usually helpful.
I also like the Git command line. Over years, I developed the following workflow.
I would begin by creating an empty commit that described what I was about to do.
git commit --allow-empty
Then I would edit some files. Once my first, rough sketch was done, I would take a pause mentally. This would also be a great time to commit.
git add -p && git commit --amend -C HEAD
Then I would go back to editing the code. Making the code compile, filling in the blanks, handling scenarios I’d omitted, etc. At natural pauses in the middle, I’d come up for air, and update my commit.
git add -p && git commit --amend -C HEAD
This cycle would continue, until the task was done.
So far so good, but it is a lot of typing for something I need to do around a hundred times on a productive day.
There are two ways of handling this repetitiveness - Using one of the alternative Git interfaces, and defining aliases.
For most people the alternative Git interfaces do the trick, but they didn’t for me (although since writing this, I’ve also found gitu - a Magit implementation outside of emacs - that seems promising).
So that leaves aliases. The problem with aliases is that the ideal workflow never happened as cleanly as I’m describing.
- While sometimes I know beforehand what I’m about to do, sometimes I only discover it in the middle.
- Git often makes it painful to do things. If I create a new file, then
git add -p
doesn’t add it, I need to agit add --intent-to-add
first. - Fixing up minor typos in prior commits after I’ve moved a couple of steps ahead is frequent enough that uses of
git rebase
is another dimension that my aliases need to cater to.
And I’ve never been able to come up with an orthogonal set of aliases that describe the actions I need to perform. That leaves a combinatorial explosion (gccm
anyone?) that eventually breaks down, and at the end of all attempts at defining composable aliases I find myself going back to the original approach of Ctrl-R-ing through history and tweaking the last closest matching incantation.
jj is a new tool for interacting with Git. Somewhat surprisingly, it seems to have been built around a workflow that I’d organically landed on.
Let us say I’m about to make a change. I start with telling jj about my intent.
jj new
I can tell jj about what I’m going to do either immediately (jj new -m
), or at any time later (jj describe
). Doing the change is orthogonal to adding the commit message.
Now I do my changes. Well, there is no step 2!
All changes I’ve done are already part of the latest “commit”. Of course, I can view them in detail to proofread my work
jj diff
But I don’t need to “commit” them.
At some point, when I’m doing with ironing out the changes and am ready to move on to the next thing, I can do
jj new
and that’s it.
There is a lot more to say about jj, and their vision is much more expansive than just being a Git frontend. I’ll leave you with the following links if feel curious to explore more.
-
The official tutorial is short but gives a good initial taste. From Git history (!), it seems to trace back to the introduction by the original author of jj, Martin von Zweigbergk.
-
There is a a new longer tutorial by Steve Klabnik, the (co-)author of The Rust Programming book.
-
And there is a middle length introduction by Chris Krycho (who has a beautiful website, and is also the co-author of the upcoming 2025 edition of The Rust Programming book).
The project README is also well put together, if you’re short of time and just want to explore at a high level. It also tells us about the origin of the name:
The command-line tool is called jj for now because it’s easy to type and easy to replace (rare in English). The project is called “Jujutsu” because it matches “jj”.