Marcus Kazmierczak

Home mkaz.blog

Trying out Jujutsu VCS

Jujutsu is a new version control system that I came across from a recent post on Hacker News. It has been out since at least 2022, so not brand new, but considering git is now 20 years old it is a child in comparison.

I was initially skeptical of Jujutsu, it made bold claims being so much easier to use and more powerful than git. I've never really found git to be all that complicated, sure when you get into weird branching/rebasing and other scenarios it can get gnarly; but day-to-day standard flows all fairly straight-forward and wasn't really sure what we'd need in a new VCS.

What's funny, awhile ago I wrote an article titled "Don't be a git, just use subversion" that questioned do we really need a new VCS. I thought the power of sequential version numbering in SVN, and the complexity of branching in git was too much for the vast majority of people. I don't still have the post, but here's the Hacker News discussion calling me an idiot.

In my slight defense, I'm not against everything new. I embraced subversion immediately when it came out to replace the atrocity that was CVS. So learning from the past, I thought I'd give Jujutsu the benefit of the doubt and give it a try.

So far, I don't hate it.

It took a bit to get comfortable, most tutorials and docs focus on the more complicated stuff. So I'll start with the basics, how to get started alongside your current git projects.

Install: brew install jj or your package manager of choice.

Use jj git init --colocate to start a jujutsu repository alongside an existing git repo.

Jujutsu may feel backwards to git. Every change is automatically staged and added to the current changeset. So in a sense you create the commit first, you then make changes which are automatically applied.

Here’s my common workflow:

  1. Use jj new to create a new working space to make your changes.

  2. Use jj desc -m "Describe change" to describe the working space. This is the commit message, and can be changed at any time.

  3. Make Changes

  4. Everything changed gets automatically staged
  5. Be careful, if you have anything that is not in .gitignore it will get added
  6. If something gets added, you can untrack a file use jj file untrack [FILE]

When you're done. Repeat by creating a new working space: jj new

The previous working space is now a commit in your git repo.

Here’s what that workflow looks like for adding this article to my existing repo.

  1. First run jj new and create an empty working space

  1. Create article which gets automatically staged:

  1. Describe the working space: jj desc -m "Add jujutsu article"

Run jj new to create a new working space for next change.

You can see the previous change is a commit, using standard git log

Here’s the jj log after adding two additional changes, adding images and article to home page.

Now, I won’t go into the complexity but you can go back and edit any of those previous commits using jj edit changeID or reorder the commits using jj rebase. Let’s save that for a Part 2.

Git branches are called bookmarks in Jujutsu, I believe initially they were called branches, but they are slightly different enough they were renamed to bookmarks to keep the concept different.

Looking at the jj log above there is a bookmark called trunk and trunk@origin. The trunk bookmark is my local git branch, where @origin is the remote branch. I started on a version of trunk which had a commit not yet pushed up.

To “move” the commits made to a branch called add/jujutsu specify which changeID to add the bookmark to.

jj bookmark set -r tylvvqpn add/jujutsu

To push up this bookmark to GitHub to create a PR:

jj git push -b add/jujutsu --allow-new

You’ll get a link to create a PR, or can go to GitHub and see the branch and be prompted to create PR.

If changes are made on remote, say someone else contributed to that branch, use jj git fetch to pull in the changes.

If I want to keep adding to the remote, I use the same workflow as above. jj new to create new working space. Make my changes, jj desc to describe change.

I then need to repoint the bookmark to the change, this time

jj bookmark set -r @- add/jujutsu

You can use the revision shortcut @- which is the change before the current working revision, signified by the @ character.

You can see that my local bookmark is different than the remote.To update the remote, jj git push

You can now merge the change on GitHub, and then update your local repo using jj git fetch.

If you are a yolo solo developer, not working on branches and using PRs, you can use the same process above, but just use the trunk bookmark. Repoint trunk to whatever revision you want, push it up to GitHub and bob’s yer uncle.

Those are the basics of jujutsu. If you want to learn and play with, I would start with these basics and slowly grok what is happening. You will hit upon new things you want to do, and add piece by piece to your repertoire.

As you get yourself into and out of trouble, look up jj undo and jj abandon commands to help. It is also all just git - so you can fall back on any of those commands to straighten things out if need be.

Play around and explore.

Benefits

  • You don't have to git mv FILE or git rm FILE it all just happens. You focus more on what you are doing and less on thinking about what is staged, what isn't etc.

  • Removing the staging step and use of jj new feels more lightweight, since descriptions are optional too and you can go back and edit, it makes it easy to start a new commit on each idea

  • Getting more advanced, but using split and squash make it easy to keep changes together. For exampe, I'm collecting changes to this article while updating various other parts of my site. So, if I remember I'll run jj edit [changeID] for the commit I have for this article. If I forget and make a change to the article in the middle of other changes, I can runjj split and remove the change to jujutsu into its own commit separate from others and then squash with my previous article edit.

Extras

  • You can use jj commit -m "DESC" which is equivalent of running jj desc -m "DECS" followed by jj new

  • Jujutsu limits the size of a file at 1MB, which a bit small. You can set in the config file: ~/.config/jj/config.toml

[snapshot]
max-new-file-size = "10MiB"

Resources