Switch to Jujutsu Already: a Tutorial
Posted3 months agoActive3 months ago
stavros.ioTechstoryHigh profile
heatedmixed
Debate
85/100
JujutsuGitVersion Control
Key topics
Jujutsu
Git
Version Control
The article 'Switch to Jujutsu Already: A Tutorial' introduces Jujutsu as an alternative to Git, sparking a heated discussion about the merits and drawbacks of switching from Git to Jujutsu.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
2h
Peak period
103
0-12h
Avg / period
21.9
Comment distribution153 data points
Loading chart...
Based on 153 loaded comments
Key moments
- 01Story posted
Oct 13, 2025 at 5:22 AM EDT
3 months ago
Step 01 - 02First comment
Oct 13, 2025 at 7:04 AM EDT
2h after posting
Step 02 - 03Peak activity
103 comments in 0-12h
Hottest window of the conversation
Step 03 - 04Latest activity
Oct 17, 2025 at 2:56 PM EDT
3 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45566421Type: storyLast synced: 11/20/2025, 8:52:00 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
On the other hand, I have issues with Jujutsu, one of which completely prevents me from using it in some projects:
* No support for git submodules. One can dislike submodules as much as they want, if I need to contribute to a repository using them, I can't use Jujutsu.
* The signing support is very annoying with a security key. Even if I configure 'sign-on-push', it will access the security key every time it tries to check the signature, which is pretty much every `jj st` or `jj log` after something has changed locally. I don't need to check my own signatures, IMO they should be checked on fetch and on push.
* There is no way to configure a 'defaultKeyCommand' like in git, which I now rely on (because I have multiple security keys).
In addition, mixing Git and JJ will result in your repos becoming really slow when you do need to run some Git operation.
I like the idea of it, but there's so much inertia around typical git workflows that revolve around the GH pull request model (with the only difference being the use of trunk based dev or some git-flow like branching strategy) that it'd be hard to change without a lot of buy in.
I still think back to Phabricator and its approach to code review, noting that it sadly never got wider traction despite having notable benefits over a completely entrenched status quo.
I love this description and it describes how I work with git. When I’m doing things locally I’m constantly committing small wip commits. When I get something the way I like it I’ll interactive rebase/just back it all up, and then create the perfect little boxes. I guess I should try jujutsu since it sounds like it might be even more for me. Although if you can’t get to the perfect boxes at the end I don’t know if I’d like it.
The only part that piqued my interest is merges being always successful and conflicts just sitting in the tree, waiting patiently to be resolved... It's the next logical step after being able to commit without synchronizing when we all moved away from SVN.
That looks actually nice, but it seams to require macOS.
jjui (https://github.com/idursun/jjui) makes it all that much easier too
It's cool that it exists, and it's impressive that it is built on top of git itself. If you (like the author) want to use it, then more power to you. But I have yet to be convinced by any of these articles that it is worth my time to try it since nearly all of them start from a point of "if you hate Git like me, then try this thing".
If anyone has a link to an article written from the point of view of "I love or at least tolerate git and have no real issues with it, here's why I like JJ," then I'd be glad to read it.
https://www.stavros.io/posts/switch-to-jujutsu-already-a-tut...
That having been said, I didn't hate Subversion either. It was fine.
I think you linked to the same post as OP, though?
I used bzr after SVN, but my larger point is that it's all fine, the question was whether you want to go through some short-term learning for long-term gain, or if you want to keep using what you know. Either is fine, I'm still using vim as my editor, for example.
Was it better than CVS in some way? Sure.
But git is just better in so many ways. Back in the day I used git exclusively with git-svn at a place that was still stuck with SVN and I had a blast, while everyone else didn't. I just never had any of the problems they did.
I'm not entirely sure what pain people speak of with git. I found the transition very natural. And don't come talking to me about the "weird command syntax". Some of that was specifically to be compatible / "intuitive" / what they were used to for people coming from tools like SVN.
Sure you gotta learn about "the index", understand that everything is local and that you have an origin and local copy of all the labels (also sometimes called branches or tags) you can attach to commits. That's about it for the normal and regular use that someone would've had with SVN.
It can't be that SVN is bad and git is better but also that git is fine even though jj is better.
You start out the article with hate for git without explaining what you actually don't like, then here on HN say "I don't hate git". A command called `fuckgit`? Because you need to re-clone? What are the things you commonly do that require this? I've never encountered it. Maybe you're just too advanced a user for git and jj really is better for you. But for us lowly regular users I really do not see an issue.
Some of the benefits you tout, like "editing a commit and you don't need to commit it yourself"? I'm sorry but I want to be the one in control here. I am the one that says "I'm done here, yes this is the new version of the commit I'm comfortable with". I've specifically forbid Claude to add, commit, push etc. for example.
It also breaks your "you need to stash" argument. I don't stash. I just commit if I have something WIP that needs saving while I work on some other emergency. There's no reason not to just commit. In fact I do that all the time to checkpoint work and I amend commits all the time. It's my standard commit command actually `git commit -a --amend`.
Automatic "oplog" of everything Claude did, IDE style: sure, maybe. Though I've yet to see that need arise in practice. Just because I have Claude et. al. now, I don't believe changes should be any bigger than they used to. Nor should my "commit early, commit often, push later" practice change.
I start out the article saying I never understood git, and why does it matter what I don't like? That would only matter if I were trying to say that git is bad, but I'm not making a comparison. I just think jj is better-designed, and that you should try it.
> Some of the benefits you tout, like "editing a commit and you don't need to commit it yourself"?
I never said that's a benefit, I just said that's something jj does differently. I `jj commit` when I'm done with some work anyway.
> It also breaks your "you need to stash" argument. I don't stash. I just commit if I have something WIP that needs saving while I work on some other emergency.
In that case, you'll like jj, as it handles all that for you.
Your comment is coming off as a bit defensive, I didn't write my article to attack git. If you like git, keep using it, I prefer jj and I think other people will too. It's hard to get started with because its workflow is different from what we're used to, so I wrote the tutorial to help.
Blue speech bubble with literally the text: "If you don't like Jujutsu, you're wrong". This is text. There's no "tongue in cheek" voice and body language here, even if potentially you meant it that way. But given how the article itself starts, I don't think there was any of that to transport :shrug:
Actually, it does bear saying. And I do think that if you say "everyone that doesn't think jj is better is wrong" you have to explain what you really don't like or get. No it's not needless, because not everyone has your experience. I really do not understand your pain points unless you explain them, because I've never felt them. Either because I did understand the part you didn't, because I don't need to understand that part to use it well (cutting the decision/knowledge tree in your head is a skill by itself I've found over the years - sometimes you do have to accept magic! E.g. I don't need to understand exactly how any specific LLM works to use it well) or because I simply never had a need for the kinds of feature that trip you up.Except Git doesn't do it differently here. Git only provides an additional way to commit temporary changes, you still can commit them how you like. In fact a stash are just two commits.
I probably would have stuck with Sapling, but my company switched to git and the jj integration was cleaner -- especially being able to run in colocated mode: your project root directory has both .jj/ and .git/ subdirectories, and you can use both jj and git commands without much trouble. If someone gives me a git commit hash, I can just use it directly with jj.
Sapling is good. I'm still fond of it, and in fact still have a few repositories I haven't switched over yet. But being able to do everything with a single tool is useful, plus jj gives me some extra capabilities over sapling (or at least things that I don't know how to do as easily).
When I was an intern at GenericCorpo we had days we couldn't work because SVN was down. WTF was that?
Idk man, the first two paragraphs of the article very much make it sound like you hate git.
> Over the past few years, I’ve been seeing people rave about Jujutsu, and I always wanted to try it, but it never seemed worth the trouble, even though I hate git.
> I don't hate git
but
> I have my trusty alias, fuckgit
Someone who doesn't hate git would have named this alias quite differently...
But hey, it's not my alias. I'm just saying that the way I read it didn't suggest hate, just a little cleverness. I can't speak for what the author was thinking.
There's nothing wrong with taking the time to learn how to use a bad UI, especially if there's no other option. But don't mistake your personal mastery of git for evidence that it's better than jj.
In all likelihood, the git proposal you allude to would not extend further than adding a bit of persistent metadata that follows commits after "destructive" changes. And even then, it'd be imperatively backing into the change-as-commit-graph data model rather than coming by it honestly.
> If you actually take time to learn your tools and how they're intended to be used, there's really not reason to learn jj IMO
This is like saying if people take the time to learn curl, there's really no reason to learn Firefox.
And it doesn't suggest to me that you're all that familiar with jj!
- automatic rebasing! goodbye to N+1 rebases forever
- first-class conflict resolution that doesn't force you to stop the world and fix
- the revset/template languages: incredibly expressive; nothing like it in git
- undo literally any jj action; restore the repo to any previous state. try that with the reflog...
No amount of learning git nets you any of these things.
I always introduce jj as a better git ui.
And when you rebase, the commits lose their identity since commit hashes are content-addressed, despite having an identity in people's minds - a new revision of a commit under review is usually logically the same unit of change, but git doesn't have a way of expressing this.
jj, as I understand it, addresses these pains directly.
Since when does rerere not work with rebase anymore?
>> Git records merge resolutions
isn't true either.
There's a semi-recent addition that makes it a single command, the --update-refs flag to rebase (along with the --rebase-merges flag, formerly called --preserve-merges).
Would be nice, if it would also have a flag to choose that behaviour.
It turns out there were a lot of things that I was not doing with git because with git it would have been painful.
Now my PRs are split into human-sized commits that each contain a set of changes that make sense together, and I keep moving changes around during development to keep the history tidy, until it's time to send the pull request. If a commit introduces a typo, the typo fix should go into that commit so the typo never happened in the first place and you don't get reviews like "please fix this" and then "oh wait I see you fixed it in a later commit".
And sure, with git you could checkout the faulty commit, amend it, then amend -a and hope no one was looking, and rebase your dev branch onto the amended commit and it will often even work. Or rebase -i, sure -- have fun with it if the typo was 12 commits ago.
So I just never did that because augh.
With jj it's trivial. You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
No more rebase hell. No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually -- jj takes snapshots after every mutation and rolling back is easy. No more squashing on merge to sweep the messy commit history under the carpet. No more juggling index and staged files and stashed files and all that messy business. Everything is just suspiciously straightforward. To think this could have been our lives all along!
And I'm not looking back.
It's not that I dislike git. It's just that I love jj.
That's my workflow in Git. It is sometimes painful, but only because other people don't do that.
It is less work, if you use git --fixup=old-commit-hash and then use git rebase --autosquash. The --fixup step can even by automated, by using git-absorb, but this needs to be installed separately.
> You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
That sounds the same in Git?
> No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually
When do you need to do that? The only case in which I messed up my repo, was when I had a harddrive crash and recovered commits manually from git objects, because the other files were corrupted.
> rolling back is easy.
Yes, that seams a bit easier, but reflog still exists.
> No more squashing on merge to sweep the messy commit history under the carpet.
This is just as well a stupid idea in Git and I hate that. This seams to be cultural and is not suggested by the tool itself.
> No more juggling index and staged files and stashed files
I find these useful, but you can also use Git without them. Just always use commit -a and commit instead of stashing.
> That sounds the same in Git?
I've always struggled with this myself, and would like to update my git knowledge. Can you walk me through the commands to do this? Let's say the commit id is `abcd1234` and it's 5 commits ago.
In JJ I'd do this:
Or if I was feeling more pedantic I'd do:The git commit step can also be replaced with git-absorb, if you have this installed and abcd1234 was the last time you modified these lines.
The second approach is this:
So you would need to stash after the fixup commit and pop the stash after rebase. Or use autostash.
As for effect on the workflow, you can just continue to work and commit and then call autosquash in two weeks, when your about to merge. This also has the benefit, that Git (by default) only alters commits nobody has used yet.
The second approach has the exact same amount of commands. The first has 2 more. The add is necessary, because Git separates committing into two steps, which has other benefits. If you would want the JJ behaviour you can call commit -a. The autosquash is necessary, because you don't need to use fixup with autosquash, you can also do it alone, which is recommended if this fixes something, that is already in an older release.
As for jj, JJ and Git are much more close than C and Rust. JJ tends to have slightly less commands, but only because what are flags in JJ are separate commands in Git. The impression I get from these posts, is that it would have been doable with similar effort in Git, but they just never bothered.
Also I prefer refining stuff we already have instead of throwing it all in the bin and stating it's obsolete.
I don't think it would have been doable. I hear this question/comment sometimes. I sent https://github.com/jj-vcs/jj/pull/7729 to have a place to point people to.
> The project started as an experiment with the idea of representing the working copy by a regular commit. I (@martinvonz) considered how this feature would impact the Git CLI if it were added to Git. My conclusion was that it would effectively result in deprecating most existing Git commands and flags in favor of new commands and flags, especially considering I wanted to also support revsets. This seemed unlikely to be accepted by the Git project.
This doesn't support what you said?
> I don't think it would have been doable.
This only states that JJ has a different user model, with a different structure of commands and flags, not that it magically does things that are impossible in Git.
Btw., you could just link to the commit diff instead. And are you quoting yourself?
-----------
Oops, now I see the issue, you misunderstood me.
> but they just never bothered.
"They" referred to the authors of blog posts. I didn't want to claim, that it would be a good fit to merge the JJ user model with the Git user model. My claim was that the approaches people learn with the JJ user model aren't exactly difficult in the Git model either. People just reconsider their approaches when they touch a new tool with the experience they gained since starting to use Git. They just never considered that approaches with a tool they have been using for years.
My impression from our Discord server is that quite many JJ users actually are Git experts who have been creating clean commits for years. I'm one of those people. It's not a coincidence that JJ's CLI makes it easy to create clean commits - it's designed for that from scratch.
I'm not sure if I would like it, because I care about reproducibility of commits so I want commit hashes to stay the same after a rebase. Does it support --committer-date-is-author-date ?
I'm also somewhat wary of additional layers on top of something.
That flag seems a bit weird, though. Wouldn't you want to keep whatever the committer date already was? Why would you want to reset it to the author date? Of course, after you have passed the flag once, any subsequent uses will have the same effect as keeping the committer date, so maybe that's why it's good enough. Maybe it works the way it does for historical reasons (I happened to see that it used to be passed to `git am` back when `git rebase` was based on that).
Where jj shines is advanced workflows that aren’t practical with git. If you aren’t interested in those then it doesn’t give you as many benefits over git.
If you are breaking down your features into small PRs, stacking them, etc…, then jj is super helpful.
I feel like I’m doing something wrong, as I haven’t seen this mentioned in any tutorials, but I don’t know what! :-/
Can you try it on a fresh clone and see if it still happens?
Really? Pointing out that a tool is difficult to use seems like an excellent argument to promote the use of a different (supposedly simpler) tool.
Specifically in the case of git, I'm glad it was not difficult for you, but it is undeniable that it is a very difficult tool for many people to learn.
> Needless to say, I just don’t get git.
What is there not to _get_, honestly? And why is jj so easier to get?
The author seems to focus on how great it is to make changes to your commit history locally, and that you shouldn't worry because it's not pushed yet.
The thing is, I don't want automatic. Automatic sucks. The point of version control is that I am able to curate my changes. The guards and rails of git is what makes me feel safe.
I am still failing to see why JJ is superior to git, or whatever.
There are some convention people follow when working with git to make it safe to use. But those aren't git's features -- they are ways to avoid confusion.
[0] https://www.sublimemerge.com/
Your real mental model of git should be an acyclic directed graph where the nodes are commits and the edges are ancestry. Commits represents snapshot of the project's state. Tags and branches are just text pointers to commits in the graph.
If you use this mental model, suddenly things like git rebase or git reset become far less mysterious and arcane since they are just simple graph operations. Like `git reset --hard X` means "Make current branch's text pointer point to X"
What was holding me back turned out to be the fact that git has too much magic (it updates branches automatically when you commit, rebasing "does stuff", conflict resolution was just arcane).
Jj exposes all that into simple, composable principles, making everything click.
Considering jj is built on top of git, doesn't that mean jj has even more magic? That's like saying React is too magical so we should use Next.js instead (which is built on React).
Maybe you just mean that jj has a more intuitive CLI than git?
What am I supposed to do, use the UI plus jj, and prompt an LLM to use which: git, or jj, in case I am too lazy to think of the right command in the remaining one percent of cases?
But in general, I like the "less states and DVCS features than git" approach, but would not switch back to mercurial just to avoid the whole "should we rebase or create merge-commits" discussions in our teams due to having a single default that might not be optimal for everyone, but just works.
If it doesnt do anything you already need, then the maintainer is likely to add it quickly - its rare to find someone so responsive
Always the same starting point: "I don't understand how git works".
If you can't understand git, one of the most used tool in the whole industry, this is a *you* problem. You MUST take the time to understand how it works properly. Every job you'll get and every projects you'll work on will use a Version Control (at least I hope).
Abstracting this knowledge by using a tool that does things quite differently won't help you at all on the long run.
Git rebase is like programming with punch cards compared to jj’s rebase being like writing Python.
https://ofcr.se/jujutsu-merge-workflow/
Maybe more articles showing galaxy brain SCM workflows that are difficult under git but possible under jj and are killer for productivity is a better marketing strategy for jj.
Which every articles I read on JJ failed to do correctly.
My point is not to avoid using other tools to do your job. My point is that if you don't understand something, using a layer on top of it won't help you at all understand things in the long run.
I want to see JJ articles made by Git experts; not JJ articles made by people who fear Git lol
> Since you're a git expert, you understand the underlying mechanics of your tool and you can explain to me why a command like Git rebase is better in JJ than in git.
I'm not the person you asked but I can try to explain (I started the jj project, fwiw). Some things `jj rebase` does better than `git rebase`:
* It rebases whole trees/graphs of commits. This is the scenario described at https://stackoverflow.com/questions/17315285/rebasing-a-tree.... Bookmarks/branches are always updated accordingly. `git rebase --update-refs` can do that these days, but still only for one range of commits at a time (i.e. one leaf commit).
* It lets you rip out some commits of a stack and put them somewhere else. This is the `-r` flag. See https://jj-vcs.github.io/jj/latest/cli-reference/#jj-rebase for some examples. You can also reorder commits by doing things like `jj rebase -r X::Y --insert-after Z` to insert the range of commits from X though Y after commit Z. You can parallelize parts of the graph by doing e.g. `jj rebase -r C --insert-after A --insert-before D` to take an initial linear graph A..D and make C parallel to B.
* It doesn't stop when there are conflicts. You can instead resolve the conflicts when you feel like it.
* It's able to rebase merge commits well, even if there are conflicts and/or conflict resolutions in them. `git rebase --rebase-merges` with the "ort" merge strategy and rerere enabled gets close these days.
* It's about 100x faster by not touching the working copy unnecessarily. `git replay` also does that.
I just sent https://github.com/jj-vcs/jj/pull/7733 to provide some more detail in our "Git Comparison" doc.
We had somewhat the same exchange on reddit a few weeks ago under a similar article if you remember :)
Once again, I really appreciate the time you are taking to explain those things!
Everytime you chip in, it's always spot on and crystal clear. This is the kind of informations those people should put in their articles.
Have a good day and keep up the good work!
Git is a bad teacher. There are a lot of things that are profound yet easy to grasp when learned and other things are called bad products. Git is one of them.
Moreover, you can use jj almost completely seamlessly with a git repo - including PRs etc to github. I do it daily and no one is the wiser.
Unfortunately, I agree.
It is both ubiquitous and so unnecessarily complex. The fact that all developers are required to memorize at least a few of its inscrutable incantations reflects poorly on the industry and on the judgement of its practitioners.
> If you don't like Jujutsu, you're wrong
It would be much more convincing if they had any idea of git that they were comparing it to.
Edit: read more of the post and I still don't see the big deal. It's like rebase/edit with a bit less typing.
> One day I randomly decided to try again, but this time I asked Claude how to do
As this seems to be the reason for having "a great idea" , an alternative explanation
Mise and jj (and jjui) are my favourite tools, by far.
In my opinion having multiple package managers only complicates the system and causes more problems then it solves. In fact I think the package manager is the OS. I can swap out the kernel and all the userspace with it, but changing the package manager will be disruptive.
I come to this conclusion because there's always a large amount of people saying "if you dont understand, let alone have mastered, git, then you dont get to have an opinion"
So, clearly these people similarly dont use ease-of-use abstractions like programming languages
> if you dont understand, let alone have mastered, git, then you dont get to have an opinion
Eh Yeah kind of? If you use the wooden end of a hammer to try to hammer a nail, you don't get to complain that a hammer is a shitty tool for hammering nails without looking profoundly stupid. And complaining about people complaining about this is just ignorant.
Of course people are allowed to have opinions on git (or anything), but if your 2nd sentence is 'i have a command that deletes the .git folder and replaces it with a fresh copy', it shows that maybe the author is still in the hammering nails with the wooden part phase.
Conversely, git requires a whole apprenticeship before you can be effective.
Moreover, there's MANY git "masters" who are effusive about how they'll never go back to git after switching to jj.
If it is just easier and better for beginners and experts, maybe it's just better.
If you want the contents of the file at some old commit 0a123, `jj file show -r 0a123 <filename>`. If you want to overwrite the current version of a file with the version from 0a123, `jj restore --from 0a123 <filename>`.
How do you "checkout single files" in git? What does that mean?
Checkout means that the version of some files at some commit is "checked out" in the worktree. So all these things are mostly the same in Git terms. The arbitrary split into switch and restore is confusing to me.
I think jj's mutable revisions are best thought of as automation around `git commit --amend && rebase_everything_after_this_commit`. If you're not using that kind of flow with Claude, you wouldn't use that kind of flow with jj either.
I routinely use .git folders that are 11GB (+4GB checked out files) and 10k+ branches without issue.
I don't have very many branches, though. 13 branches, 6838 tags.
Some caveats: jj's version of `blame` (jj file annotate) is painfully slow and I usually run `git blame` instead. (Which is a general thing: if anything is missing or slow, you can always just do it with git.) jj's rebase is insanely fast -- especially if you add in the time to manually resolve conflicts, since a good chunk of the time I don't have to spend any time at all since the conflicts are only in experimental twigs that I may never need to go back to (and if I do, it's fine to wait until I need it).
Great transition. Strong recommend.
What command is he talking about? When you get that git is a graph manager, it gets really easy to manage, very quickly..
Also, while I think the UI of git can be improved, it is not more complex than it needs to be.
9 more comments available on Hacker News