Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Why?

Many people I know don't have much motivation to give Jujutsu a try because, they say, "Git works just fine". Fair enough! I assume that you are reading this book because you are curious to see what Jujutsu brings to the table.

A natural question to address is why Jujutsu exists and what problems it solves.
Spoiler alert: the funniest part is that it solves problems that you didn't know you had1.

So, the first question is: does Git really work as well as we think?

Isn't Git just enough?

A scenario I like to present in job interviews is: pick your favourite technology and imagine you had a magic wand. What are the 3 things that bother you most and you would change?

Without questioning that Git is a masterpiece of engineering (I'm myself a huge fan!), can we agree on 3 things that could be improved? Try answering this on your own.

Here's my take.

1. Git has too many building blocks

Consequently, some find it difficult.

  • Some people find the index a bit mysterious.
  • detached HEAD stresses them out.
  • They are not sure when to git reset with either --soft, --mixed or --hard.
  • Or when to use --staged with git restore.
  • When they mess up, they panic and struggle to undo their changes.

Could Git be simpler, without sacrificing its power?
With my magic wand I would summon a smarter model, based on far fewer, more intuitive elements designed to be composable. The result: something smaller yet more powerful than Git itself.

Jujutsu does this magic. With a tiny fraction of building blocks, it makes those operations that were intimidating or even impossible with Git straightforward.

2. Git's interface is not always consistent

"How can I view a list of all tags?"

"git tag", replied Master Git.

"How can I view a list of all remotes?"

"git remote -v", replied Master Git.

"How can I view a list of all branches?"

"git branch -a", replied Master Git.

"And how can I view the current branch?"

"git rev-parse --abbrev-ref HEAD", replied Master Git.

Steve Losh - Git Koans

My preferred example of inconsistency is the index, which for many Git novices is a source of confusion. It's the staging area where you forge the next commit. Pro Git calls it the "proposed next commit snapshot". Is it the next commit? Not quite. In fact, it is a quasi-commit.

  • It has a SHA1 checksum (tail -c 20 .git/index | xxd -p), but it's not its address. A branch cannot target it.
  • It's not a pointer to a tree-object like a real commit. So, you can't use git show to inspect its content. You have to use git diff --cached.
  • If you want to move a commit around, you use git rebase. If you want to move the index, you need git stash.

Index is a special case, so it needs special commands, completely inconsistent with the commands for real commits.

Magic wand, let me turn the index into a real commit, with all its power. Presto! All the commands involving the index and commits become consistent with each other. Well, actually, they collapse to the same commands.

API consistency results from the absence of special cases, and Jujutsu embraces this idea: it removes all the special cases. You still want to stash changes, don't you? But you don't want to have special stash pop, stash drop, stash apply commands: you want to reuse the building blocks you have already learned. Welcome, composition.

3. It's a leaky abstraction

Git feels hard at first, but it stops fighting you once you learn a bit of its internals.

Why doesn't git diff show staged files? How do you use reset and checkout to restore changes and start over? How do you undo a rebase? The answers click once you know a few implementation details such as:

  • Branches are mere pointers.
  • Git keeps the working directory, the index and the repository as three separate areas.
  • Commits are immutable, and any operation manipulating the history will just create new ones.

When people struggle with Git, it's often because they have built a wrong intuition about how it internally works. But, is this their fault? I don't think so.

If I had a magic wand, I'd ask for a tool with a truly opaque abstraction, completely hiding its internals, one that captures what I mean, the what, quietly handling the low-level mechanics, the how.

To see what I mean, take the example of "undoing stuff". You can always consult the Git reflog, check what you did and figure out which low-level operation you need to revert a change.

  • You did git rebase -i HEAD~2. To undo, git reset --hard ORIG_HEAD
  • Did a git stash apply? You need git stash drop.
  • Did a git tag? You need git tag -d
  • Did a git add? You need git restore --staged <file>
  • Did a git commit --amend? You need git reset --soft HEAD@{1}

That is: you need to derive the inverse operation for the command you want to undo, and this often requires knowing Git's internals.

What's the equivalent in jj? jj undo. Want to undo a fetch? jj undo. Want to undo a rebase, a merge, a commit, a conflict resolution? jj undo, always jj undo. It's consistently jj undo, no matter what change you made. jj undo is one of the Jujutsu killer features. I promise, you will wonder how you could have worked for so many years without undo. We'll see this in detail later.

First, let me show you an example with deeper consequences. We will talk about a well-designed piece of Git and you will learn your second Jujutsu command.


  1. This reminds me of The Blub Paradox (Paul Graham - Beating the Averages). "[People] are satisfied with whatever language they happen to use, because it dictates the way they think about programs.".
    That is: until you've used more powerful tools, you don't experience their advantages as missing features of your current tool. In a sense, you can't miss what you've never had.