Jujutsu VCS Introduction and Patterns
33 comments
·February 4, 2025bkolobara
gechr
Although it is currently undocumented, since v0.21.0 you can make `--edit` the default by adding the following to your configuration:
[ui.movement]
edit = true
Ref: https://github.com/jj-vcs/jj/pull/4283cupofjoakim
I think I'm at risk of sounding like a broken record here. I've read about jj many times now but i'm still confused as to what problem it actually solves. I get the same feeling as when some dude wants to sell me on using vim as my primary code editor - arguments are there but it doesn't really solve an issue.
I'll go over to jj when that's the primary tool for the job, or when I can see something that beats the git cli hands down. I'm 100% on the path of least resistance when it comes to tool adoption.
saulrh
The thing about jj is that it doesn't actually enable any new capabilities. I tell people to use emacs or vim or vscode or whatever instead of notepad because it gives them new capabilities, things that are simply unavailable unless you're talking to an LSP or running a full-powered scripting engine. jj doesn't make anything possible the way going from notepad to a real editor does. What jj does do is it makes everything so much easier that you can now actually use all of those features that git theoretically gave you. Rebases? No more fiddling, no more wedges, no more digging through the reflog because you fat-fingered something, you just go `jj rebase` and... that's it. And if you get it wrong, you just do `jj undo` and... that's it. And if you just had a six hour manic coding marathon without committing anything and now you want to spread its batch of changes back down through your patch stack, you just do `jj absorb` and... that's it. It's not the difference between notepad and emacs where you're going from no LSP to LSP, it's the difference between emacs@2016 where LSP support is a week-long adventure and emacs@2024 where LSP support is five lines copy-pasted out of the info page.
sunshowers
As a source control expert and jj's number one fan [1], I would count being able to defer merge conflict resolution as a new capability, FWIW. In general I think jj's greater than the sum of its (very good) parts because of how its features work together to create a coherent and pleasant user experience.
[1] the top testimonial on https://jj-vcs.github.io/jj/latest/testimonials/ is mine
mamcx
I was a happy mercurial user until market forces and consulting needs made me, regrettably, use the inferior, more complex, more error-prone git.
I have used it already for a few years and can't for the life of me figure out how to solve problems with it. I just have a bunch of aliases that abstract away for the inconsistency of its commands.
Now, I switched to `jj` a month ago and basically, I have learned around 60%-ish of it. And more importantly, I have gotten out of a bunch of serious trouble (you can UNDO!!!!) already.
But if this rant is not enough:
* You can UNDO. Everything. That is the major thing
* You can switch from one `branch` to `another` and leave things incomplete, even conflicts, that is nice.
* The command made sense
* Nobody else knows you use `jj`, so no barrier to adoption.
* Rebases are not painful anymore. Stacking prs are finally nice to author, even of NOBODY ELSE KNOW IT!
The major troubles:
* Not yet support for major tools, ides for it. It stays in `detached head` which is not as nice as showing the current branch on IDEs, and when you are fixing conflicts some tools do not get the diffs.
* No mature UI tool. I use `gg` which is fine enough
But the above is just temporal problems. Git will never be `fixed` or improved, so is pain forever.
12_throw_away
> I was a happy mercurial user until market forces and consulting needs made me, regrettably, use the inferior, more complex, more error-prone git.
Right? I even started with git, and had been somewhat comfortable with it for years. Then I joined a mercurial shop, and was more proficient with `hg` in 1 month than I had been with `git` after 5 years. It ruined me on git forever, I can't see it as anything other than a mess of wrong abstractions.
And unfortunately, these days I'm back using git with the rest of the world. Can't wait for the day when Jetbrains gets a good plugin for either `jj` or `sapling`, and I never have to google another git command again ...
dartos
I switched from git to jj a few months ago, so I may have some insight.
I used it at work, where everyone used git, and there were 0 issues.
What I really like about it is how changes are sort of soft committed right away and, when I checkout a different branch or change, I don’t need to stash my changes and remember the stack of stashes.
Rebasing and merging feel a little easier, but that might just be because “ours” and “theirs” doesn’t get flipped during rebasing.
I also like the ability to checkout an old commit, make a change to it, then have all my more recent commits automatically get rebased (not exactly what happens, but the analogy works)
All in all, it’s a solid, compatible, incremental step forward in VCS.
The only tangible downside for me is that it doesn’t support git hooks
password4321
> I also like the ability to checkout an old commit, make a change to it, then have all my more recent commits automatically get rebased (not exactly what happens, but the analogy works)
Can anyone comment on how Jujutsu "rebases" multiple commits at once vs. git prompting each one be signed (eg. touch Yubikey), and how it looks afterward in git?
sunshowers
There is no substitute for trying it out for a few days. It will quickly become apparent why people like it so much.
cube2222
So, I've felt pretty much like you - that is, I was happy with git, never really had major problems, and was generally content. Which meant that even though Jujutsu was on my radar for a while, it took me until now to take it for a spin.
In practice, for most bits and purposes, Jujutsu is just designed really well around a core set of primitives, which you use to achieve basically all your use-cases, which in git are spread across many fairly "special-case" features. This means that arbitrary "change tree modification" are pretty trivial.
The easiness of jumping into non-branch-tips and editing them with descendants automatically rebasing is also nice, to me, and fits in well with my workflow. Stacked PRs[0] are much less annoying than in Git thanks to auto-rebase as well.
Finally, I think the "Working on Two Things at the Same Time"[1] pattern is not easy (if even possible?) to achieve with git.
But all in all, as I wrote in the article's conclusion, the reason to use Jujutsu is that it just makes your VCS usage more pleasant, while generally not interfering with anything else as it effectively works as a git frontend.
[0]: https://kubamartin.com/posts/introduction-to-the-jujutsu-vcs...
[1]: https://kubamartin.com/posts/introduction-to-the-jujutsu-vcs...
Hasu
> when I can see something that beats the git cli hands down.
Then you should switch to jujutsu several months ago.
It's the biggest improvement to my development workflow in over a decade. The last change that was as big was git itself.
zellyn
I can second this opinion. The moment I read "something that beats the git cli hands down" I command-F searched for "hands down" to find this comment or make it myself.
abound
> I'm 100% on the path of least resistance when it comes to tool adoption.
Different folks will have different preferences when it comes to adopting new tools. Some like "tried and true", some want to experiment and see what's out there.
I (an avid `jj` user) like to think I want some pragmatic blend: I want tools that help me get my job done, and otherwise get out of the way. So if I think there's room for improvement in my workflows (in this case, managing 10-20 ongoing changes at a given time across 5-6 projects), I'll experiment with new tools that can help reduce the friction for me.
Like you said, there's functionally nothing `jj` can do that `git` can't, Jujutsu literally uses git as the default backend. For me, the power of Jujutsu is the massively reduced cognitive overhead of using it. My thoughts more directly translate to `jj` commands and I rarely have to think about it, even with complex stacks of changes.
hellcow
Stacked PRs with multi-branch rebases are effortless. Conflicts are actual things in the history that you can come back to later. Everything is automatically committed, so I don't lose work from a bad reset/stash pop.
Maybe these don't help you with your workflow. But in my case these solve the biggest problems I had with git while still being fully compatible.
qudat
Editing changes in place is very handy. This is especially useful for range-diff workflows when you want to see what has changed between two patchsets (eg diff of diffs).
I’ve been slowly working on a patch-bin service that only has access to patchsets and doesn’t have access to the git repo itself. As a result the best we can offer is range-diff. It’s a pretty interesting workflow and makes the collaboration software easier to maintain: https://pr.pico.sh
0cf8612b2e1e
What workflow do people adopt for tools which still do not have a concept of local-only config files? For example, VSCode only has a launch.json, which should be committed, but I might need to customize it to my environment/current problem without distributing those edits.
How can I not constantly fight jj with this?
SatvikBeri
I use the squash workflow for this. I do my work on change N+1, which includes all the local changes I don't want to merge. When I'm ready to make a PR, I squash my edits into earlier changes, then `jj git push -c @-`, which will send everything up to change N. Once merged, I rebase change N+1 onto the new master.
cube2222
I think you could achieve this with a variation of the "Working on Two Things at the Same Time" pattern[0], also explored more widely here[1] (with e.g. using private commits).
Basically, just have a local-only merge-change that combines whatever you're working on, with all your local modifications. You can then even just create new changes on top of the `<dev>` change, and then rebase each into your branch when you're done with it, for even better ease-of-use (using `jj rebase -A name-of-branch`).
You can also mark those local-only changes (both the merge-change and the local customizations) as private changes, to make sure you never actually push them.
[0]: https://kubamartin.com/posts/introduction-to-the-jujutsu-vcs...
[1]: https://v5.chriskrycho.com/journal/jujutsu-megamerges-and-jj...
sunshowers
The usual way this is done is by having a sample file checked into the repo (launch.sample.json?) that developers can copy locally and customize.
currymj
it’s great that jj just looks like you use git to other people, so doesn’t inconvenience them.
how does it work the other way? if i’m using jj, and my colleagues are using git, how does it cope? in particular what if they are using git in a really depraved way (like just add all files and always commit everything, etc.)?
steveklabnik
> how does it cope?
You're both operating on git repositories, so there's no issues. You can think of jj as an alternate git client.
I have used jj for about one month on a project with a colocated git repo.
So far, I enjoy it a lot. Previously I would have a bunch of 'wip', 'fix typo' commits, but my commit history got much cleaner with jj. It's very easy to jump to old changes and apply fixes right in the place they belong. All changes + tests are now committed as one unit. I would never bother to do it in git, but because it's so easy now, I do it all the time.
Also, the possibility to add a description/message at any time, not only when you "commit" something at the end, is super useful. I use it as some kind of TODO list. Basically, I create a bunch of empty commits with a message and then just start from the first and work my way through all of them with `jj next --edit`.
If you have some extra time and would like to try out something new, I would very much recommend it.