Everything I know about the Jujutsu DVCS right now

I create a new repository with jj git init. This creates a root commit and another empty changeset/commit on top of that. I do some work, jj tracks it. When I’m done with the work, I use jj describe to describe it/create a commit message, and then jj new to create a new set of changes.

Some basic commands and a simple workflow

The jj squash workflow can be done as follows:

  1. create a new changeset with jj new.

  2. label it with what you want to do with jj describe

  3. create another new change with jj new

  4. make some changes

  5. squash the ones you’d like to keep down into the previous changeset with jj squash. You can either use the -i file to interactively pick what changes to keep, or jj squash path/to/file.


Adding partial changes

You can use jj split filename put a file into its own separate changeset.

You can also do jj squash --from $REVSET --to $REVSET -- $FILENAME.

Or to move from a current change into its parent: jj squash -- $FILENAME.

To do this interactively: jj split --interactive or jj squash --interactive.

Generally speaking, if you find your changeset/revset has some changes that you feel like belong somewhere else, jj split is the solution, although in some specific cases, jj squash will be more suited.

I’m happy to note that this workflow is part of neither of the workflows described in Steve’s Jujutsu tutorial, which makes me feel very happy that I’ve found something new to share with the world <3

The jj split workflow

This workflow wasn’t featured in Steve’s Jujutsu Tutorial, and I found it well adapted to my use cases, so I figured I’d quickly write it up and share it.

A short summary

  1. Create a new changeset with jj new.

  2. Add stuff to this changeset. Edit files.

  3. Use jj split <filename> to make some of edits part of a separate changeset

An example

This example is Linux-based, although it should be relatively easy to adapt for many other poular operating systems like Windows and the various BSDs.

We start by creating a new working directory for this example, and switching to it.

mkdir new-wd
cd new-wd

Next, we’ll initialize a Jujutsu repo with jj git init.

jj git init

Now, let’s write a few characters to a text file for our first commit, so we’re not starting from an empty repo.

echo "Hello, world!" > 1.md

Next, let’s use jj describe to name our commit.

jj describe -m "first commit :)"

At this point, we’ve set up our Jujutsu repo and put some basic work in.

Now it’s time to actually use jj split to organise new changes.

First, create a new empty change to act as our ‘staging area’ with jj new.

Next, let’s add a bunch of changes.

echo "2" > 2.md
echo "3" > 3.md
echo "4" > 4.md

Now when we check the status of the repository with jj st, we should get something similar to

Working copy changes:
A 2.md
A 3.md
A 4.md
Working copy  (@) : nttlwzzs 6d6c07c2 (no description set)
Parent commit (@-): nlzvwkvo a02e9104 first commit :)

Our goal here will be to give each file a separate changeset.

brief detour: The Git Equivalent

What we’re going to do is basically equivalent to

git add 2.md
git commit -m "add 2.md"
git add 3.md
git commit -m "add 3.md"
git add 4.md
git commit -m "add 4.md"

Give each file in the staging area its own unique commit/changeset.

To do this with jj, we’ll use the jj split command.

We can actually do this in a single command for each changeset, if we use the -m, or --message flag.

jj split -m "add 2.md" 2.md
jj split -m "add 3.md" 3.md
jj split -m "add 4.md" 4.md

Now when we check jj log, we see

@  ryypsvnq achenet@fastmail.com 2026-05-27 18:37:55 02d215fd
  (empty) (no description set)
  xltzsxrq achenet@fastmail.com 2026-05-27 18:37:55 b6ecc470
  add 4.md
  oluuumzs achenet@fastmail.com 2026-05-27 18:37:45 7a1beb2f
  add 3.md
  nttlwzzs achenet@fastmail.com 2026-05-27 18:37:00 32fe6f72
  add 2.md
  nlzvwkvo achenet@fastmail.com 2026-05-27 18:19:37 a02e9104
  first commit :)
  zzzzzzzz root() 00000000

we succeeded in moving our changes one by one into their own changesets, and we’re left with a new empty change on top of it all.

Thanks for reading, hope this will be useful to you :)

Back to Home Page 🏡