Comment by Meleagris
2 days ago
I recently switched to Jujutsu (jj) and it made me realize that “what comes after Git” might already exist.
It turns out the snapshot model is a perfect fit for AI-assisted development. I can iterate freely without thinking about commits or worrying about saving known-good versions.
You can just mess around and make it presentable later, which Git never really let you do nicely.
Plus there’s essentially zero learning curve, since all the models know how to use JJ really well.
Yes, it’s fantastic. I have a post-tool-use hook for Claude Code to snapshot the repository for every edit. It’s like the built in file history feature but native in my VCS and works for my edits too. Don’t want to froth too much but JJ is my favourite piece of software in a while, and the fact that it’s not VC-funded is a major plus point.
Its VC funded https://www.sec.gov/Archives/edgar/data/2076429/000207642925...
Jujutsu is not "VC funded". But some of the developers, including me, work at East River Source Control (I worked on Jujutsu before that, too). The majority of the code in the project doesn't come from us -- or Google, for that matter. We don't allow people to approve patches when the author is from the same company, anyway.
1 reply →
that's a company built on top of Jujutsu, not jj itself
5 replies →
Can you expand on this? How do you achieve it? Just a WIP JJ commit after every change or something more clever?
In newer jj there’s a dedicated snapshot command but I’ve not updated yet. Pop this in your Claude Code settings.json. It will snapshot the repository, thus recording any changes. Explore with jj evolog.
In .claude/settings.json you can trigger shell commands on events like SessionStart, Stop, PreCompact, and PostToolUse [1].
I have all of them run `jj status`, because jj snapshots the working copy every time it's invoked.
You can have Claude write the hooks, but mine is:
`[[ -d .jj ]] && jj status >/dev/null 2>&1; exit 0`
[1] https://code.claude.com/docs/en/agent-sdk/hooks
The others use `jj status`, but if I were to do this, I'd use `jj log -n0`, which has no output. All you really need is any read-only jj command.
You could also turn on watchman and have this property on every save of a file and not even need to worry about hooks.
> You can just mess around and make it presentable later, which Git never really let you do nicely.
I'm surprised to read that, because that's how I've always used Git (and GitHub).
That's what I've understood to be good practice with Git, and it was liberating compared with what came before. One of the nicest things about Git is you can throw things in locally without worrying about how it looks, and make it presentable later.
I also did that with git, but it's no comparison in ergonomics. For instance, "move this hunk two commits up" is a task that makes many git users sweat. With jj it's barely something that registers as a task.
You sweat because you are working with the CLI. Git is intrinsically "graphical". Use a good GUI client or higher level interface (maybe jj) to manipulate git graphs --- stop worrying about "how" (i.e. wrangling with CLI to achieve what you want) and focus more on "what".
GitButler from OP also allows you to do this incredibly easily. This and stacked commits is IMO their main selling point.
> For instance, "move this hunk two commits up" is a task that makes many git users sweat.
Citation needed. You split the commit anyway you like, e.g. with the mouse or using cursor movements or by duplicating and deleting lines. Then you move it with the mouse or cursor or whatever and squash it into the other commit. Maybe some people never intend to do it, but then these probably also don't want to learn JJ. I guess this is more of a selection bias, that these that care about history editing are also more likely to learn another VCS on their own.
4 replies →
The problem put simply is that git doesn't support concurrency. Even if you use worktrees, git has a global lock for repo interaction.
https://www.felesatra.moe/blog/2024/12/23/jj-is-great-for-th...
Every success story and happy conversion to jj is evidence that hg should have won the DVCS war, but more importantly, that VCSes and their inherent merits and tradeoffs were always secondary to the social networks underpinning them. GitHub as a defacto monopoly really killed innovation in the VCS space, but also shifted the focus and attention elsewhere. That's why I don't think there'll be so much of a "post-git" without as much as a "post-github".
Does VCS-agnosticity actually work? It feels like a huge burden to migrate it everytime you want to have the tools from the innovation in your daily work. Also projects want to integrate project versions into each other and reference versions and identifiers are likely VCS specific. That's why I feel VCS monopolies actually has a lot of benefits.
LOL. In 2007, I did a side-by-side comparison of SVN, Mercurial and git with my codebase at work (~700k LOC). I know hg got faster eventually, but I still can't believe people say "hg should have won the DVCS war" with a straight face. It was orders of magnitude slower in my tests. Like, 20 minutes to commit large xml files (yeah, I know, but that's where we were). Not just a few ms slower, unbearably slow for several things.
I liked its features better, but chose git, and that was the correct decision.
This isn't an apology or a deflection, but different VCSes strike different trade-offs in terms of speed per workload. The mercurial storage model is comparable to video encoding in that it has a somewhat equivalent of "key frames" and alternates differential and full revisions¹. This makes workloads like bisecting or jumping to long-distance commits more efficient, at the expense of the time to create new commits.
For your use-case, mercurial has had a `largefiles`² extension for a very long time (long before git-lfs).
> I liked its features better, but chose git, and that was the correct decision.
Anyhow, my personal story with git is that I bought into the hype and social effects without really challenging my assumptions ("it must be the best, everyone says so"), until I got very fed-up with its obnoxious UI, and someone on IRC told me "ehh, give hg a shot". Nowadays, I mostly interact with git repos through hg-git and jj.
¹: https://www.kernel.org/doc/ols/2006/ols2006v2-pages-91-98.pd...
²: https://wiki.mercurial-scm.org/LargefilesExtension
What's the difference between "snapshots" and git commits? In my mind a git commit is already a snapshot of the repo and the changes one staged. In what way can you move around more freely than what one can do with magit, deciding for files, hunks, or even single lines of code, whether or not they get staged and committed?
You're right that git commits are snapshots.
jj is very non-modal, that is, it doesn't tend to have a lot of state that commands rely on. As an example of what I mean, because jj does not have a staging area, everything is already committed, which makes it very easy to say, move to a different commit: you don't need to stash your working copy, as jj has already stashed it for you. Similarly, due to the auto-rebase behavior, you can be working in one part of the tree, realize something somewhere else should be moved, and go rebase that without even moving to it at all!
As a small example: say I'm working on something, and I find a typo. I want to send that typo in as a PR, but I don't want to do it as part of my work. I can do that with:
1. make the change in my current working copy (@)
2. jj split -o trunk (selecting the typo contents to split off the typo fix into a new change on top of (hence -o) trunk)
3. jj log (go check out what the change id of that change is
4. jj git push -c <change id I found in 3>
No need to even move my own HEAD (in git terms), just knock it out inline in a few steps while I'm working.
Now, as for magit, I don't use it, and I know that those that do love it and it does make some of this stuff easier. But not everyone can use magit. And there are "magit, but jj" projects as well, but I can't speak to them or which is best at the moment.
Technically, nothing. But psychologically git commits represent a unit of completed work, whereas with AI agents what's needed is a kind of agent-wise undo history such that you can revert back to the state of the repo 1 minute ago before Claude did an oopsie all over your repo.
You can definitely use git as a backend for building such a system, but some extra tooling is necessary.
Just create a new branch before you implement new features and if the agent messes up don't merge the branch.
That way you get the best of both worlds. The buggy code is still there in case it's needed but it's not in the main branch
2 replies →
git checkout @{1.minute.ago}
> You can definitely use git as a backend for building such a system, but some extra tooling is necessary
Is it? There’s the stash for storing patches, the index for storing good hunks, branching for trying out different experiments. You can even use worktree if you want separate working directory especially when there will be changes in the untracked files.
Git has a lot of tooling for dealing with changes, directly or at the meta layer.
It seems to have been build on great idea. Git's "plumbing" is just a set of snapshots of the tree, and everything above is built on that so replacing the porcelain with something better fitting the problem is far more useful than trying to reinvent the wheel and making yet another distributed tree snapshot based VCS just to reinvent user facing tooling like the other VCS tried
I gotta say, jj was not something that interested me before, but that's a compelling pitch.
I was doing something with jj snapshots with AI now that you have mentioned.
I will admit, I didn't know jj but I wanted snapshots so I used it, so then when AI made some changes and kept on going and I wanted to go back to a particular change and I used ai to do that. It was actually really frustrating. To the point that I think I accidentally lost one of the good files within the project and I had to settle on good-enough which I had to try to get for hours to that particular point.
My point feels like I should either learn jj properly to use it or to at this point, just ask AI agents to git commit. Another point but I was using ghostty and I had accidentally clicked on the title bar and somehow moved the folder to desktop, I wasn't thinking the most accurately and I just decided to delete it thinking that it must have copied it rather than moved it. (Also dear ghostty why do you make it so easy to move folders, it isn't the best of features and can lead to some honest errors)
My face when I realized that I have deleted the project:
Anyhow decided to restore it with ~/Trash but afterwards realized that the .git/.jj history is removed because it deletes hidden folders (from my understanding) so I definitely lost that good snapshot. I do have the binary of the app which worked good but not the source code of it which is a bit frustrating
These were all just an idea of prototyping/checking how far I can move things with AI. Yeah so my experience for that project has been that I could've even learnt a new language (Odin) and the raylib project to fix that one specific bug in lower time than AI which simply is unable to fix the bug without blowing the whole project in foot.
I think the takeaway is to have good backups man. I mean I was being reckless in this project because I had nothing to lose and was just experimenting but there have been cases where people have lost databases in prod. So even backups should be essential if you find any source code which is good to be honest.
I am sure you guys must have lost some source code accidentally which you have worked upon, would love to hear some horror stories to hopefully know that I haven't been the only one who has done some mistake and to also learn something new from these stories. (I am atleast happy in the sense that I learnt the lesson from just an tinkering thing and not something truly prod)
you'r doing great. we all learn these things. AI assisted development makes it really easy to redevelop, especially since it sounds like you were vibe coding it out.
Definitely not true about models knowing jj. I've had latest opus and gpt fail at revsets and fileset syntax, even hallucinating subcommands like jj move (maybe it existed before, interface is not stable). Luckily it's easy enough to not need them most of the time.
Yes, I use Claude with jj often, and it occasionally tries to use older commands like move. Most of the time it gets it right for me though, often plugins and such say to use git explicitly, and that's where it tends to stray.
I like darcs, so I am rooting for pijul.
https://pijul.com
is there a jj hosting service?
GitHub.
Jujutsu has changed how I work with git. Switching tasks is just "jj edit <change>" or "JJ new <change>". The only thing it can't do properly is git worktrees (it doesn't replicate the .git dir to the worktrees, breaking tooling that relies on git) but there is a (old) issue relating to it. Not sure on the priority, though.
Anyway, YMMV, but I love it.
https://tangled.org/ supports many jj features, but they seem to only offer public repos.
We are working on something https://lubeno.dev
Looks like still a bit early for me, but if you add an RSS feed to your blog, I would at least be reminded to check it out again later :)
I know of one: https://lubeno.dev
Any service that hosts git?
We use GitHub at my work. And I think I’m the only one using JJ.
Isn't jj git compatible so you can just use github?
Yes.
Do you not use git branches? Your use case was why git was made.
I do use git branches, but they solve isolation, which isn't my pain point with git.
When I'm using agents to code, I don't want to have to stop what I'm doing and commit known-good state to the repo every few minutes.
jj just snapshots everything automatically, so I know I've captured that state, and I can look back and curate it all after the fact.
It's like the shift from manually saving Word documents to autosave, but instead of forcing it with git, I can use JJ which has been intentionally designed for that workflow.
Why not just ask your agent to check in before every change? And then squish before you push or share. Works great for me and easier than convincing coworker to switch off git.
The biggest problem with Jujutsu is the name. I would love to hear a Swedish person try to pronounce it.
Its a backronym (or whatever you call it) that cones from the actual name, “jj”, which itself comes from the ease of typing jj on a keyboard
The logo is a pair of bluejays, so I've taken to casually calling it twojay with some of my coworkers.
"I can iterate freely without thinking".
Vibecoding moto.