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.
The jj squash workflow can be done as follows:
create a new changeset with jj new.
label it with what you want to do with jj describe
create another new change with jj new
make some changes
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.
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
jj split workflowThis 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.
Create a new changeset with jj new.
Add stuff to this changeset. Edit files.
Use jj split <filename> to make some of edits part
of a separate changeset
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.
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 :)