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

Squashing Changes

Important

You learn to replicate Git’s squash and you see when Jujutsu automatically abandons empty Changes.

The jj squash default parameter are clever:

jj squash -f A -t B FILES
  • Omitting FILES moves all edits in the Change.
  • Omitting -f or -t implies the Current Change @.

So:

jj squash -f A

moves all edits from A to your Current Change.
And:

jj squash -t B

moves your current edits to B, wherever it sits in history.

This technique is truly powerful. It lets you edit something here and send it somewhere else. Notice an unrelated typo while working on a feature? Fix it on the spot and squash it where it belongs. Spot some work needed in another branch? Write the change here and move it there. Do you see how this move allows you to work on multiple features simultaneously?

You should also see jj absorb in its proper light: it’s this exact move, applied automatically to every chunk. I promise that once you get the hang of it, there is no going back.

Abandoning Changes

After a squash, Jujutsu abandons empty Changes automatically.

For example:

jj log -r "n::zx"
○  zx
○  v
○  s
○  n

Warning

You want to move the edits in v into n. How?

Tip

jj squash -f v -t n

You get:

○  zx
○  s
○  n

Notice that v disappeared: it was left empty. Use --keep-emptied if you want to retain it.

What Happens To Messages?

Jujutsu does it best to preserve information. If squashing abandons a Change with a description, Jujutsu interactively prompts for you to merge the message in the target Change. Alternatively, you can either directly set it with -m, or you can use --use-destination-message / -u to keep the target’s message.

Quiz Time!

Check out this sloppy mistake:

jj show n --git
--- a/src/App.js
+++ b/src/App.js
...
+    <button
+      className="square"
+      onClick={handleClic}    <-- typo
...

Oops, Clic instead of Click. But look! I fixed the typo in the next Change qq, with the very expressive message “Fix”:

jj show qq --git
-      onClick={handleClic}
+      onClick={handleClick}

I could have amended n, directly.

Warning

Get rid of the noisy qq, integrating the typo fix in qq-.

Tip

Option 1:

jj edit qq
jj squash -u

Option 2, without moving:

jj squash -f qq -t n -u

And qq is no more!

Just jj squash

Finally, the most common use. Running bare jj squash:

  • Moves all edits (no files specified)
  • from the Current Change to its parent
  • and, if the Current Change has no message, it abandons it and promptly provides you with a fresh new one.

Say you are on a branch tip:

@  sw           empty                               <-- your working area
○  zx           Click alternates Xs and Os main     <-- your target
○  v            Click sets a X
○  sn           Square has state

You code in @, then run jj squash. Your edits are absorbed by zx and you receive a fresh new @.

See where this leads? It’s the equivalent of the Git index! Let’s explore the Squash Workflow, which builds on this idea. Then you’ll never miss Git’s index anymore.