I can understand if you need to run a CI or unit tests locally. Is that it?
I am not attacking JJ, I genuinely can't understand its value in my current workflow.
I can understand if you need to run a CI or unit tests locally. Is that it?
I am not attacking JJ, I genuinely can't understand its value in my current workflow.
I find jj overall most useful for separating the concept of a machine-level commit history that saves every change from a human-readable commit history . jj has really nice tools for cleaning up your commits for review while still retaining all the mechanical changes in case you need to get more granular. (Of course, there are many other tools to do this, like magit – I just find jj to work best with my brain.)
Workspaces/worktrees are best when you have long-running tasks where the state of the disk is important. Local "CI" is a good example – kick off a long test run on one workspace while starting a new task in another. Another example these days is stuff with Agentic LLMs, e.g. I might create one workspace and ask Claude Code to do a deep investigation of why our AWS costs went up.
Maybe from the kind of work I do? either CI is failing because of something really simple, or something really complicated that means getting a product setup and producing debug messages. If it's a critical fix on branch A, then I'm not working on branch B. I'm testing branch A locally while CI does its thing
There is a lot more to jj that makes it nicer than git, but it's mostly a bunch of small things that jj does nicer, that cumulatively add up to a significantly nicer experience.
> I don't see how creating a worktree in a new folder and opening a new editor is more convenient than creating a branch at a certain commit.
Worktrees are about being able to work on multiple branches at the same time, fundamentally. When you want to be doing something on one branch and something else on another branch simultaneously.
That does mean it's, IMHO, a fairly niche feature.
1. Stacked PRs. I like to be kind to my reviewers by asking them to review small, logically-contained pull requests. This means I often stack up chains of PRs, where C depends on B depends on A, and A is being reviewed. If I receive feedback on A, jj enables me to incorporate that change within A, and flows those changes down into my dependent branches. I can then merge and close out A, whole continuing to work on B and C. Achieving this in raw git is labour intensive and error prone.
2. Easily fix up commits. I like to work with atomic commits, and sometimes I realize that I've made a typo in a comment, or a small error, or missed a test case. Jj makes it really trivial to timewalk back to the commit in question, fix it and resume where I left off.
3. Decompose a big PR into multiple PRs. This is the flip side of point 1: I can take my own big PR and rearrange and partition the commits into A, B and C so that they can easily be reviewed.
In general, jj seems to encourage and reward you for being disciplined with your commits by enabling you to be more flexible in how you stage, review and ship your code.
On the flip side, if you're the kind of person who is used to typing `git commit --all --message "xxx"` you might not get as much value from jj until that changes.
https://github.com/tdhopper/wt
with some custom shell aliases to make it easier.
I have a recent annoyance that's solved by work trees: running multiple AI agent instances locally in parallel, without containers or VMs. Jujutsu isn't even needed for this, 'git worktree' is adequate. Granted, self-hosted agents is a niche use case, but IMO, worktrees are the simplest and most elegant way to scale up GPU utilization once the model is loaded. Other alternatives are multiple checkout locations, containers or VMs each requiring a 1:1 ratio to agent instances.
As for worktree, jj or git, it has become the defacto way to work on multiple branches in paralell, using AI. Unlike the non AI workflow where you don't switch often, working with AI involves more branches that can be worked on in parallel and switching back and forth quite rapidly.
Meanwhile, there are git tools that solve the above three problems. My organisation uses `git-spice` (https://abhinav.github.io/git-spice/) which tightly integrates with Github to give you stacked PRs, editing of branches and management of your stacks in Github.
I've been trying jj for a while now because Steve Klabnik heavily recommended it, and so far it hasn't clicked in as nicely as my existing git setup.
But when I first moved to jj I tried to make it work as closely to git as I could. The model I used back then was to have a commit that I meant to upload eventually, and then a working commit on top of that. Then `git commit --all` was `jj squash` and `git commit foo bar` was `jj squash foo bar`.
Eventually I got lazy. It was an extra command, and I almost never have the situation where I don't want to include a file. In the rare case that I do, I'll create a new commit with `jj new` and squash that file into there (you could have a shortcut for it, but the long form is `jj new -m "foo changes" --no-edit && jj squash --to @+ foo`, and then keep working.