I absolutely love jj (just check my HN comment history). One thing I'd love to see in jj though that git does better is copy tracking. If somebody renames a file upstream, and you go to rebase your commit that touches that file onto main, jj doesn't handle this very well compared to git.
Do you have any idea if this is coming to jj soon?
If there is only one implementation of jj, and one vendor of jj, and it is too complex to have multiple implementations of, is this just an attempt at trying to lure people into vendor lock-in and profit off of that? Especially considering how core and critical infrastructure a VCS is to modern software development?
Git has lots of implementations across lots of programming languages. No vendor lock-in is viable for git. Is vendor lock-in inevitable for jj? Git was started to not have to use a proprietary VCS.
> Git was created in April 2005 by Linus Torvalds, the creator of Linux. The Linux kernel project depended on BitKeeper, a proprietary distributed VCS. When a licensing dispute made BitKeeper unavailable for free, the project urgently needed an alternative.
Git had a very small initial implementation, while jj is under development for years and is large. If jj is not too complex to have multiple implementations, why have new implementations not sprung up by now? Is it the Google CLA, or are too few people using jj, or is jj too complex, or some mixture of all of the above?
> Second, I thought about contributing a fix to that table, and then I saw the contributing requirements:
> > Contributor License Agreement
> Nope, not happening. Nobody should adopt this until it's been freed from that requirement, either by getting the project to remove it or by establishing a version of the project that takes contributions without that requirement.
> why have new implementations not sprung up by now?
Nobody wants to yet?
FWIW, while there aren't multiple reimplementations of the core yet, there ARE multiple GUI and wrapper projects that fulfill various needs, if you're just looking for outside contribution as a health measure.
Jujutsu also started out very small, just like Git did. The core concepts aren't too complex. But this is 2026, not 2005 or 2019. Most of the modern Git implementations are extremely large, highly optimized and featureful codebases that are difficult to replicate. Many of Git's performance and structural improvements over the last few years have nontrivial implementations and designs. Jujutsu is also a large, featureful codebase. You can't build a modern Git implementation with all of the highly optimized goodies (multipack indicies, partial clones, etc) and a good UX without a lot of code and work. Or any version control system, frankly. It's just how it is.
- Gitoxide is 80,000+ lines of code.
- Git itself is over 170,000 lines of code.
- Even "Game of Trees" or "got" by the OpenBSD developers, which is a wholly separate project that has its own porcelain, is +120,000 LOC.
- Jujutsu itself is about 100,000 LOC.
- JGit for Java is around 200,000 LOC.
These are all roughly approximate and include things like testing code (but I think that's fair because tests are part of the project). All of these projects started small years ago, and are now large.
> If jj is not too complex to have multiple implementations, why have new implementations not sprung up by now?
"Make multiple implementations" is not, in and of itself, particularly valuable without some underlying justification to do so. It also is not how (AFAIK) any other version control system has ever worked; Git's "identity" as an on disk format is a particular design choice (with pros and cons), so yes you can get multiple tools with varying levels of features that agree on the basic disk format and poke at it. But most projects just don't work this way, much less other VCSs; there also aren't really many "Linux re-implementations" beyond toys because it is easier to just collectively contribute with each other, because Linux is not a "standard" written in stone, but a living and breathing thing.
> There is a mandatory CLA you must agree to. Importantly, it does not transfer copyright ownership to Google or anyone else; it simply gives us the right to safely redistribute and use your changes.
[Emphasis from the source]
Does this make it possible for the jj organization to make the implementation closed-source and proprietary, and abandon the open source version, taking all the contributed changes from volunteers and other organizations with them?
It gives Google the ability to use the source code under whatever terms they want. It does not change the Apache licensed code at all, which can still always be used under that license.
The CLA is Google's in this case. It gives them the right to distribute your copyrighted work. It also has some terms that say Google could sublicense and redistribute the jj codebase under another license -- which means they could for example release a copy of the jj code that was under MIT, or GPL2, MIT-Apache, etc. Or proprietary, even.
But the thing is, Jujutsu is under the Apache 2.0 license right now. You are within your rights to use Apache 2.0 in proprietary products. Literally anyone, at this exact moment, could clone the repo and integrate it into a proprietary product, or share proprietary binaries built on the code (rename it Gugutsu VCS) without giving up the source, as long as they obey the ASL 2.0 terms. The CLA really has nothing to do with this fact.
If you are personally worried about your personal copyrighted patches going into proprietary products -- or if that's your only worry -- you basically need to avoid contributing to all projects that are not using a copyleft license; just avoiding CLAs or whatever isn't enough. This has been true for a while.
If you are worried about a "rug pull" the next question is whether the developers can actually do that. That is a matter of social configuration of the project, not licenses. The thing with "rug pull OSS projects" is mostly about ownership and labor. Licenses and CLAs really don't matter much if 99.8% of development comes from one group of unified engineers. Such a setup is risky even with a 0% chance of any license changes. Their company might fail or they might all get fired. You didn't get rug pulled, but the project might die, which is basically just as bad.
But for Jujutsu, there is no majority of developers from any one company, and significant amount of code comes from the community, so the answer is more or less "no, we can't do that even if we wanted." The best we could do is start a whole fork and lose a significant chunk of the community and contributors. There isn't any one group of people with enough of an iron grip to do that without sustaining massive losses.
I think people sort of get "Can this become proprietary", with "Is some <bad outcome> possible" -- in this case Jujutsu's code can absolutely "become" proprietary already in a real way. You can just go do that now. But a lot of "rug pull" things are prevented, I think, simply due to the fact we have a robust and strong community outside the (paid) developers
Ultimately, for a non-copyleft project, non-assigning CLAs like the one Jujutsu has are basically just annoying, legal ass covering mechanisms for Google's sake. I also do not like the CLA, it's just basically an irrelevant piece of paper in the grand scheme to me, though. The Linux kernel DCO is basically just a CLA with fewer words, motivated by similar concerns to not get backstabbed due to the business logic of suing people.
If we got rid of the CLA for Jujutsu, I personally think it would probably still be nice to ask people to respect the DCO.
Because jj is backend agnostic, you can use it with whatever VCS you'd like. git is very common. So it has the exact same amount of "lockin" as git does.
If there's interest in alternative implementations, then they'll happen, simple as that. The reason it hasn't happened is that there isn't any desire for one.
You can still tell actually - jj writes a change-id in the git commit object header, which remains there as it's pushed around. It's just typically not made visible by regular things. (I wonder what other random garbage has been hidden in git commit headers that noone has seen)
Huh, fortunate for it that GitHub (especially) preserves it then!
I wonder how guaranteed that is, can imagine GH deciding to 'clean' it (how much data can you put there theoretically? Or to close a range of potential security issues) and suddenly relatively niche but genuine uses like jj's change-id are unintentionally not preserved.
Will this have any chance if Jujutsu/jj doesn't get more traction? The effort to learn a new VCS is less than for a programming language, but many developers have not learned git in depth, and Mercurial and others have not gained a lot of traction.
I'd argue that the reason a lot of developers have not learned git in depth is because it's actually kind of terrible from a UX standpoint (lots of inconsistent naming of things and somewhat leaky abstractions), and that Mercurial faced an uphill battle in large part because it lacked compatibility with what people were already using. I haven't used Mercurial, but from what I've heard quite a lot of how jj does things is similar to Mercurial, just in a way that's compatible with git. I haven't used git directly for over a year in favor of using jj despite exclusively using git repositories, and no one I've worked with has even needed to be aware.
> I'd argue that the reason a lot of developers have not learned git in depth is because it's actually kind of terrible from a UX standpoint
Not really. I remember my early years with git and the favt was that I never needed more than clone, add, commit, pull and push. While I’ve done some mistakes that got ne to learn more, especially with creating branches and undoing. I’ve never needed a lot, even when I started using GUI which exposed more concepts.
Why? Because I have no understanding of version management and how it’s useful in a dev workflow/release process. I was just using it for checking in work.
Since then, I’ve read the “Pro Git” book, learned how devs and teams handle versioning and devel a good understanding of how git can help me in my coding process and general software development. And it’s very good at what it does.
Not really. Learning the piano and learning music theory is two different things but tied together. One is skill and muscle memory, the other is theory and understanding. It’s the same with git and version control. One is a process and the other is a tool.
I don't think this framing makes much sense; playing piano isn't a "tool" that you use to achieve some other task, it's literally the goal itself. Using git is not the goal, it's the tool I use to do something else, and needing to learn the underlying theory of how a tool works that's only a small part of how I do my job is not a good user experience.
The goal is to produce music, and such music is generally constrained by music theory. Using git is to version control some software, and version control is dependent on the programmer/team workflow.
At the team level, it’s guided by the release process, configuration management, which version is canonical. At the programmer level, it’s usually guided by how to switch between task, how easy to explore an idea and save the resulting experiment, how to reset the code to a know state and how to replay a previous changes on top of new changes.
So you discern what you want to do (which is independent of the tool), the learn how to use git to do them. If you start from git, you’re going to be confused, just like someone opening autocad with no knowledge of engineering drawing.
"Properly" is doing a lot of work here (Claude would say it's load-bearing ;) If one's needs are modest, then no, the 4-5 basic operations don't need a 400-page book to understand, and are quite proper for version-controlling one's software.
Yes, really. You just proved the other poster’s point. He says “a lot of developers have not learned git IN DEPTH” and you respond by saying that’s not true because you’ve gotten away with just using a small subset.
Git is quite powerful, but the cli is a train wreck of complexity and inconsistency. Learning the options to one git command means you’ve learned the options to exactly one git command. No other git command is required to use the same terminology. Personally, I was stuck in “git basics land” (all the basic commands you list) until I adopted Magit in Emacs. IMO, the Magit team deserves a medal for making git usable at an advanced level.
I don’t have an opinion about jj yet, but no one can hold up git as a pinnacle of great source control. Yes, it’s powerful, but it’s a UI train wreck.
> He says “a lot of developers have not learned git IN DEPTH” and you respond by saying that’s not true because you’ve gotten away with just using a small subset
You forgot the “because it's actually kind of terrible from a UX standpoint”. My stance is against that. I haven’t learned git in depth because I never knew any other workflow than code and check in the changes. There’s not a lot of guides on how version control can help in the software development process.
It wasn’t until I got involved into OSS that I learned more which in turns give me the motivation to use and learn about git in depth. I’m also using magit (after a tour in various GUI) but for me it is to git what vi is to ex. Direct interaction instead of a command prompt.
> I’m also using magit (after a tour in various GUI) but for me it is to git what vi is to ex. Direct interaction instead of a command prompt.
I'm not sure I understand how "I use a specific text editor with a specialized interface into git that's superior" is a counterargument to the first-party tool having horrible UX. That seems basically the exact same as what I was saying about jj, except via emacs instead of a CLI. Either way, we've opted out of the actual experience of the tool in favor of using an alternative tool that operates on the version control.
Magit doesn’t anything that is not readily available in git. Most of magit usefulness comes from “active objects” (meaning you can act directly on the report of some commands like git-log) and quick command construction due to transient and autocompletion.
Can you give me a a terse summary of what "checkout" means that doesn't involve needing to either list or ignore several very different types operations?
I would say “align the worktree (or part of it) to a specific state previously saved in the repository.”
The repository is a store, you check out the previously saved instance of a file, a group of files, or a subtree. In that regards, switching branches and restoring files is actually the same thing. A commit stores whole files and branches are pointers to commits (which update themeselves).
What is version control to you? For me it’s basically being able to store and retrieve snapshots of code at different instances of time, where each instance has its own significance. Checkout have a very precise meaning in that regards, just like add and commit.
Maybe you can explain how is it leaky based on your understanding of version control?
As a Mercurial fanboy, git took off thanks to being from Linus, and a requirement to contribute to the Linux kernel, from there the adoption wind was in motion.
As someone who was a mercurial fanboy too, critical element was that Github happpened for git while mercurial had nothing comparable - and before anyone points at bitbucket, it fucking sucked in UX
TBH learning git in depth was a hindrance for me learning jj - for my first few weeks I kept instinctively looking for complex solutions to simple problems and being confused, when the answer was always "use the tools you already know"
As a concrete example - git has one set of commands for managing commits, a different set of commands for managing the index, a third set of commands for managing stashes, a fourth set of commands for managing the working directory, and a fifth set of commands for managing conflicts -- in jj all of those things are a single concept with a single set of commands, equally (if not more) powerful, but also simpler
We liked our old look, but one funny thing about how things are going in the world: our old color scheme was too close to what happens when you ask Claude to generate a site, and so even though we paid a human to build it, we didn't want to communicate slop, especially because that's not what we did!
Nick Noble is our designer, he put in a bunch of work on this, and I really like it too.
Jujutsu is apparently the name of a version control system, for anyone else confused how the creator of a thousand year old martial art had joined them.
Thanks, I was trying to work it out in my head. I knew brazilian jiu jitsu was 20th century, and I was like "but wait, is jiu jitsu itself not that much older, that seems very surprising."
Someone will have to explain the value proposition to me...
We have git.
jujutsu works with git.
git can do everything jujutsu can do (otherwise, jujutsu couldn't work with git).
Thus, jujutsu is a UX / new steering wheel.
ERSC is trying to be a GitHub competitor with what surplus value?
Don't get me wrong, GitHub has a slew of its own problems, but I have not seen any commentary on how ERSC addresses any of the downfalls GitHub has too. We're jumping from one frying pan into another, currently-cooler one?
What about SourceHut? Codeberg? They could offer the same steering wheels.
I might be mistaken, but I always figured the end goal for jujitsu was to use its own backend. Supporting git-colocation seems like a compatibility case to bring users over.
If I had to guess, then I would say ERSC is trying to build a `jj` forge based on this new hire and that would be amazing imo.
We'll be saying more about this very soon, but the short version is this: we are not building a GitHub competitor in the way that SourceHut or Codeberg are. We are building infrastructure for enterprises, not a social coding site.
While jj works with git, it doesn't have to. jj has the ability to work with many backends. Git is the popular one in the open source world, but that doesn't mean that other ones are not possible. And that's the core tech we have built.
With the rise of agents, more and more companies are running into the limits of what Git can do. It was never designed for large monorepos, and so there are performance issues, but also features that it's missing, that are important once you start trying to scale things up to an entire organization. Companies like Meta and Google ran into these things well before the present moment, but you don't have to be a FAANG these days to be running into this sort of stuff.
We also understand that incremental adoption is really important, especially for something as fundamental as source control. So our tech also has a git ingress/egress that will work with the core functionality, but more advanced things that git simply can't do will end up requiring using a non-git protocol. jj is the bridge between those two worlds.
I hope that makes sense! We have been in psudeo-stealth for a while now, this is the start of us coming out of our shell a bit and actually talking about what we're doing.
Thanks, I'm a Windows user and use Chrome myself, and on my machine it works great, but it's a pretty beefy box. I mentioned this downthread to someone else, but I've filed a bug internally and we'll make sure that it's better optimized. Thank you for the report, it's truly helpful.
If the worst thing you can say about a git hosting provider is that the performance of their blog is worse than the performance of their git servers, I think they're probably doing an okay job.
While this is true, we do care about performance tremendously, and the animation not having good performance cuts against that, so I think it's a very fair criticism. Paying attention to details matters.
That's reasonable. I mostly just found the framing to be unfair rather than the criticism itself; it feels kind of disingenuous to try to draw a connection between performance of git and performance of a webpage IMO
I'd argue that you invented some sort of link between "performance of git" and "performance of websites" that is not at all a premise I accept either, so it's not that unreasonable for me to point out that I think it's silly.
All but one of my employers have used either Github or Gitlab, and at every one of them there were a litany of complaints about whichever one we were using. It's kind of surprising to me that someone might not immediately recognize that there's certainly potential there for something better suited to what companies are actually looking for. Obviously there's no guarantee of success, and maybe the problem is too hard to solve, but that's pretty much how any company starts out!
I think it’s partly about how many steps back you take. Take another step back and you might see a new option that will in ten years be added to your list of options lots of people use and have plenty of complaints about.
I’m not saying not to try or that there’s no value in turning the wheel once more. But I used to be excited about these kinds of things and now I’m not because I’ve seen the cycle a few times now.
Yeah, it's unrealistic to think that everyone will be happy and there will be no complaints, but the median view of most products I've used at workplaces has been close to neutral. The sentiment towards Github and Gitlab seems a lot more negative overall at everywhere I've worked relative to how much people like or don't like them for personal stuff, and at least to me that seems like a sign that there's still potential room for improvement in the enterprise offerings.
I’m very excited to see the great work ERSC has/will do. When thinking about where Git lags today, I’ve come up with three categories: UX features and custom data not natively understood by the Git CLI, a stock git-http-backend that doesn’t scale well to moderate monorepo size in server compute / storage, and a wire protocol that isn’t as flexible as it could be for special requests.
But there are so many hooks into the Git workflow today, and I’m struggling to find a “user story” that would not be met by custom Git tooling. UX could be added to Git objects à la Gerrit with custom CLIs, custom Gitoxide ODB and (eventually) ref storage backends can help the server scale, and things like promisor remotes and partial clones can keep things smaller on the client side.
I’m curious what ERSC is able to share publicly about where the scaling fails with the Git specification? Is it the wire format, or the relative speed of upstreaming new things to Git? Or is the side-channel approach for storing rich data in Git objects insufficient in some way?
P.S. I wrote a blog post[1] about this a bit ago. I’m sure I’m missing something. Since I wrote it, I’ve wondered if the lack of deferred conflicts in-tree would be a scaling limiter.
Yes, it's important to realize that git is multiple things: the on-disk repo format, the CLI, and the wire protocol. Each has their own challenges, just like any project, but they can be tackled independently. But at the end of the day, there just are fundamental limits to the way that git does things that make total sense in the context Linus developed git for, but just do not in other ones. Some of those are performance related, but some of those are things like how the kernel is an open source project, and so per-directory ACLs are something that git wouldn't ever bother supporting, but are valuable for companies. We'll be talking about these things in the future, so I'm just going to be hand-wavy about it right now. But we do think that git is a really great system that has served us all well for 20 years, but just like how git displaced systems before it due to significantly re-thinking the details, for some users, making meaningful improvements over git will also require a similar significant re-think. That's just the way of technological development.
As someone trying to compete in this space: will ERSC make the change/commit their unit of code review? It's one of the pet peeves I have with GitHub et al.
We plan on building everything as individual building blocks, that you can use or not use as you wish.
Initially we won't be offering our own CI directly, you'll bring your own. We use Buildkite internally, so we'll probably share that integration first, but fundamentally you can do whatever you'd like. We won't require you to use whatever first-party offering we end up with.
I don't know how experienced you are with jj, but one thing I can say for sure is jj offers significant ux improvements over git and they plan to have a backend eventually. we might see the first implementation from ersc. and from their website I see they are already taking things like agents into account from day one. so we might be in the verge of getting something that scales better with modern day workload?
> git can do everything jujutsu can do (otherwise, jujutsu couldn't work with git).
FWIW I think it's a bit more nuanced than that. As a trivial counter example Git does not currently have a way to store conflicts inside commits[1], which is one of our major features. The way this works is that we basically store the sides of the conflicting trees in the Git object database (and another conflicted tree pointing to all of them), but the actual data structure representing the conflict as Jujutsu understands it is stored elsewhere. Git will be very confused looking at a conflicted tree object created by Jujutsu -- it shouldn't break but it doesn't understand what it's seeing. So, if a object can be stored in the database that is correct but Git can't really "view" it properly, does "git" (or capital-G Git) support it or not? Depends on who you ask, I guess. The storage layout being intimately tied to Git "as a thing", part of its identity, is one of the most interesting properties it has.
The way I see it is this. Jujutsu uses the Git storage layout on disk. But basically all of the algorithms and UX between the two are completely different. That is where most of the real differences are. To the extent we integrate with lots of fiddly Git details (eg tracking branches, remote integration etc) so that `git` commands work -- that's more necessity to make the UX nice. We could absolutely use the on disk Git format but in a way that was inscrutible to the `git` CLI, it just obviously would not be very nice.
As a disclosure I work at ERSC but I am also one of the maintainers of Jujutsu; this post is written with my maintainer hat on.
[1] At Git Merge last year, Elijah Newren prototyped and demo'd a really early and cool example of storing first class conflicts in Git, based on his work on ort-merge. So this might not be true forever :)
> As a trivial counter example Git does not currently have a way to store conflicts inside commits[1], which is one of our major features.
Yes, I like how jj does it!
Did a big `git rebase -i` yesterday and I felt stressed up, almost a bit angry, when there were some conflicts and I wasn't sure if I'd resolve all of them before it was time to leave, and work more later from a different laptop.
But with jj, no stress: I can just check in the conflicts, and later, on the other laptop: check out the conflicts and continue resolving.
(I just wish there was Git submodule support :- ))
"Can do" and "can do easily" or "can do with minimal friction" aren't the same.
I use JJ locally and for those that call it a "porcelain" or a "git UI" are missing a lot. Sure you can use it that way, but what I've found is that it facilitates (and perhaps encourages) a pretty different workflow than I'd use with just plain Git. I could pull off what I do in JJ in just plain Git... but it wouldn't at all feel natural and you can really see this when you start using a JJ driven repository with Git tools (including just the Git command line tools).
Personally, and as a mere version control user, I prefer the JJ model of version control much more than Git's. The mechanics of the UI was very easy to get under my fingers (the essentials in about a day), but getting the ideas and really getting an understanding/appreciation for the conceptual differences and their ramifications on workflow took a month or two of regular working and trying things. For me, it was worth the effort.
Absolutely everything in this industry is just a façade over the underlying ability to pass current between the source and the drain of transistors. "Just a better way to do ______" is the entire software sector.
If you ask "apart from better UX, what's the advantage of this thing?", you might as well ask "why would I buy an iPhone when my Nokia can do more things?".
While this is true and I agree with you, to be clear we do way more than just a nice UX. There is a lot of deep technical work going on here. If anything the UX isn’t the selling point, we are an infrastructure company at heart.
Git already won through Github, the Linux kernel, and other important projects. Even if you like Mercurial's syntax better (I do) and wish it won (I do), that battle was over many years ago.
jj's data store is git. You can use jj while other people on your project just use git. There's no migration of data or history. You can use Github and all of the various git tooling that exists today.
As such, the initial cost of switching to jj is zero for individuals, teams, or projects. That's huge.
jj's ergonomics are significantly nicer. Fewer ways to shoot yourself in the foot, much better merge resolution, etc.
It is possible to move one step further: use own store, speak git protocol. In the end, it is about the commit-tree-blob model. I think, the main headwind is the broad decay of interest in computer science topics.
Where can I read on jj merge resolution strategies? LLM links to Arch Linux man page and other random stuff.
Using a different data store breaks compatibility and dramatically increases the friction to switching to it. jj's superpower is that my usage of it is invisible. Right now I'm working on Github projects in jj where none of the other contributors are. Nothing about my usage of jj requires them to change anything they do.
You can speak the git protocol over the network only, but one advantage of using the same storage on disk as Git and exposing it in the same way (in a manner that keeps jj/git in sync) is that git-based tools still work. So, people still get diff markers in the gutter of their editor buffers, random scripts that do `git rev-parse` or whatnot still work out of the box, etc. This makes the experience more seamless and imposes less friction on non JJ users, eg you do not have to write a patch and add a special case for JJ because `git rev-parse` failed to run and then ask pretty please to merge it (and then keep doing that forever as you are the only user).
It doesn't sound like much, but before I started contributing to Jujutsu I was a user of https://sapling-scm.com/ -- Sapling is fantastic. It stores data on disk in git format, but back then it was not exposed to the user by default -- the .git directory is hidden away. It actually ended up causing a lot of friction that random `git` commands would not work, or tools had other various git-based behaviors. These days, sapling has a "dotgit" mode (partially inspired by jj I assume) that puts the .git directory in the root dir, so `git` commands still work.
Beyond that though, speaking Git over the network only has other complications on the client side. In particular Git clients and servers negotiate what objects each side has (given what the client requests), and from that negotiation derives a list of needed objects to give the client, and then sends a packfile for it. This is all relatively expensive to do on demand, actually, so it would make the interactivity for network operations much worse if you need to wholly translate your storage into packed objects, etc. And doing it efficiently would require you keeping a cache around that is basically a git database anyway, so you might as well just go ahead and use it. Not the end of the world in terms of downsides, but a trade-off that adds some baggage.
My relatively ignorant take is that it's pretty similar to Mercurial, except that it's compatible with git repos, which is also the answer to why it might get more traction. At least from my standpoint, it also doesn't need to get traction, because I freely use it with git repos without any of my coworkers needing to use it as well (although they might! I have no idea, just like they probably don't know I use it)
Others have answered about traction. As a one-time Mercurial user, I think the single most significant addition is first-class conflicts, so that dealing with them doesn't stop the world but can be deferred until I'm working on a particular conflicted change. (That also eliminates the need to ‘evolve’.) Easy undo is also nice.
Jujutsu is built on top of Git, so it can benefit tools in the same ecosystem (forges, CIs, code quality tools, IDEs, plugins, etc).
I have only played a little with jj and hg, but I felt that jj has a more modern UX, learning from years of Git existence (and even influencing Git, like the new `git history` command [1]). On the other hand, hg was created in the same month as Git, both trying to improve the experience of the VCSs available at the time (april 2005).
Several jj developers (especially Martin and Yuya) are former mercurial developers.
jj borrowed quite a few things from mercurial.
So, jj can be thought at least partially as a spiritual successor. Meta's Sapling is in a similar position. From this perspective, the key feature of both is transparent git repo and git remote support (hg can speak git as a foreign language, but it's limited)
I think it's closer to: develop something similar to Google's Piper as (hopefully!) an open source project and sell this to enterprise, similar to Perforce's business model but with the benefit of an excellent and well received frontend tool.
seems to respect reduce motion just fine! the animation, while extremely lovely, also does seem to be quite taxing on my GPU (~60% usage on M1 Max with Zen/Firefox, on a 1440p widescreen, which is admittedly quite a lot of space to render animation)
love the website though, i hope i one day will be able to make something that elegant!
jj is one of the few new devtools I was quite frustrated with while starting out but could see the value so stuck around and man is it so nice.
For anyone curious the big thing with jj is you can undo. Basically if you were running a rebase and bungled a commit sha or branch name, no worries undo your way out, if you forgot to push but abandoned a commit not issues undo it. Same with all jj commands.
Delta db takes this a step further and everything you edit is a change so your actual edits are also all saved.
I find non destructive-ness for as long as possible approach very nice, since there aren't as many constraints on us not being able to do it nowadays, we had limited storage and stuff in 2000s perhaps but in 2026 even with the killer SSD prices it's fairly cheap to buy more SSD, we can definitely waste 100MB per project storing redundant history we may not ever need.
Same way in photoshop non destructive editing took over, especially useful for humans, but works for AI and LLMs too, they can undo their mistakes as well.
jj itself doesn't have a native ‘push’. `jj git push` and `jj piper upload`¹ operate on external systems that don't necessarily support undoing arbitrary operations. Pure speculation, but if I were ESRC I'd make my backend handle it.
You can undo a push, yes. It undoes the local state of the remote branches after the push operation. ie: branch@origin will point at the commit it did before the push action. It doesn't actually update the branch on the remote. That would require another push operation.
A term coined within Google that describes the best part (to me at least) of jj: delayed conflict resolution.
You worked on multiple things, you sync with the upstream, then boom now you have conflicts in one or more of your local branches.
Instead of immediately presenting you a conflict resolution view (usually 3 pane vimdiff) and you'll have to resolve at the sync time, the commits are simply marked as "have conflict", and you can continue working on other things until you have time to deal with it.
And for a chain of commits that all have conflicts, chances are fixing the first conflict automatically resolves all other conflicts in the chain, thanks to the auto-rebasing feature.
How is this undo different than Git's reflog? Genuinely curious, while I have heard of jj I haven't yet tried it (I read it couldn't handle git submodules, which would have made it dead in the water for my dayjob, that seems to still be the case).
1. Reflog is very red specific that is it tracks head. JJ has op and evo logs that do that + a bunch more they track everything about the repo every possible action. It's hard to explain with going into technical depth but you can read up on it.
2. Yeah submodules aren't supported but since you can use jj in a git repo you can commit git stuff via git like submodules and then enjoy the world of jj. Since submodule interactions should be rare imho. I use it for a bunch of projects with submodules.
reflog can't quite catch every change that might happen because not everything is stored directly as a ref (ie a "head" that git tracks, like a branch pointer).
For instance, if you are interactively using `git bisect` and you mark commits as good or bad, and you accidentally mark a commit incorrectly, you have to do something like:
The reflog can't really capture this kind of thing, hence why you have a bisect log -- now a wholly separate concept that exists independently of the reflog.[1]
Another example is when you do something like screw up an interactive rebase. Let's say you rebase 20 commits and then you get a conflict on commit 8. You fix the file conflicts, and continue. You accidentally solve the merge incorrectly, continue and get another conflict -- but only realize your mistake after you start solving it. The reflog can't save you here. You have to completely abandon the rebase and start over. (This specific example might be handled better these days).
I think the biggest thing about `jj undo` is that it works everywhere. You can undo rebases, merges, conflict resolutions, copies, deletions, whatever. The secret behind it all is that internally, jj is architected in a way where implementing a feature looks like you are working with a transactional database. You actually have `begin_transaction()` and `commit()` methods in the codebase that will make changes to the commit graph visible in an atomic way. When a command like `jj rebase` happens, all of the changes it makes are inside a transaction and committed at once. Every operation in the repo is a transaction, and it all goes into a log, which records the effects of a transaction -- very much like a database system!
So "undo" just means "undo the effects recorded in a transaction" and that is about all. And so it works for everything! And this design is very easy to intuitively understand and program against, as a maintainer, along with our other high level internal APIs. Any developer can easily write code that Just Does The Right Thing and the user can undo it and it's no big deal. When I develop and work on Jujutsu myself -- like I'm actively developing new features or prototyping ideas -- I almost always _my own jj repository_ as a test repo while testing my builds.
In contrast, Git does not have one unified "transactional" layer for things like this. But not all is lost, there has been work on 'git undo' and it was implemented by... Someone who is now a Jujutsu maintainer[2]. :)
[1] Technically we do not yet have "step by step" bisect with good/bad yet (only "automatic" bisect that is one-shot), so that is something Git can do we can't do at all right now, but bear with me. :')
Git reflog is a per-ref log of its previous values. JJ operation log is a whole-repo atomic journal of changes. It's much more powerful. You can e.g. undo a change deep in history that already had multiple descendant branches (that jj rebased for you).
Since jj snapshots the commit you're editing a lot, you can often even jj undo an accidental edit to a just-created file that in git would have still been uncommitted.
We (East River Source Control) don't run Jujutsu, it does not "belong" to us -- it is a community project! Nothing has or is changed. Most of the contributors have nothing to do with us/Google/whoever. We get tons of great contributions from highly experienced and talented individuals. It's healthy, check it out: https://github.com/jj-vcs/jj/commits/main/
Most of the maintainer stuff is also overhyped in a way (OSS maintainer-heads know this). The maintainer group is largely structured to just keep things moving; not really a privilege but a responsibility -- making sure things get merged, doing technical reviews, ensure builds are unstuck, and hitting the green approval button. Our own community members also do code review, find bugs, triage things, answer questions, help get users unstuck, etc. We are very much not alone, and I have great confidence in the constitution and strength of the community itself as someone who has been around the block a few times.
This is going to sound silly and "guy approves of himself" adjacent, but I've been doing OSS maintainer stuff for like 2 decades at this point, and jj is truly a gem as a project. It is vibrant, and the community is generally speaking insanely talented (huge number of git powerusers), and we have a weird dogfood advantage where people use the tool to contribute right back to it. Martin did an awesome job setting the tone of the project just through his behavior before many of us joined years ago.
As I said elsewhere: I work for ERSC and I am a Jujutsu maintainer. This is just me speaking candidly on my own behalf.
tell that to Doug Englebart or J.C.R. Licklider-- the idea of human-computer symbiosis predates basically all computers that we would recognize as such today. crazy how it is only really now becoming true in the way that they envisaged in the 1960s.
The things I am most interested in right now are jj and llms. And the intersection between the two. I'm thinking a lot these days about how agentic development is changing our industry, with source control being one part of that.
I like the idea of jujutsu, but I must not operate at a scale where its "killer features" would truly shine. Git hardly ever gets in my way, I have never had to do complex octopus merges or anything like that. It's usually: feature branch, implement, merge, and occasionally fix a merge conflict. I've never thought to myself "git is so frustrating I wish there were something better" because I only use the same 5 commands over and over every day and they never get in my way. Not to mention jj has its own share of esoteric syntax with all the "@--+::" business and I'd have to re-write my brain to learn that instead of `ref~N`, etc.
I was a skeptic until a few months ago. It’s my daily driver now. I’ve got sizable amount of people committing to the same repo, many are not skilled with git. So I deal with weird crazy “how did you ever get the repo into this state” issues not infrequently.
JJ is just so low friction. The seamless and painless shuffling of commits, working up and down the commit chain without explicit rebasing, unchanging change-ids. The min identifiers in change-ids being highlighted. Being able to make commits and worry about the message later. Snapshots of changes while you are working serving as a tool agnostic undo.
Painless and sensible cli args that are vastly more consistent than git.
Superior conflict handling.
You can “jj undo” anything and it works perfectly.
It’s fabulous.
> "@--+::"
I have no idea what that means and I’ve never had to type anything remotely like it.
The rev specification language is pretty elaborate but you don’t need to know it.
jj seems to be falling off in terms of active development, https://github.com/jj-vcs/jj/graphs/contributors , and a lot of the GitHub repository has not been updated for years. Why would anyone invest in and spend time on learning a technology that seems to have lost steam?
Marketing push on Hacker News and elsewhere aside, jj also has the issue that it does not seem to have multiple implementations in multiple languages. In the current top thread, https://news.ycombinator.com/item?id=49527748 , people argue in favor of both Firefox, Ladybird, Servo, et cetera, such that they are not bound to one vendor and one implementation. Git has multiple implementations across multiple languages, entirely appropriate for core infrastructure like VCS. Where is the C or second Rust implementation of jj? And if there is only one implementation of jj, is jj appropriate for usage as a VCS?
Is jj too complicated to have multiple implementations?
Same experience. At first I really didn’t get it and now I could never go back. The ease of rebasing, renaming, reordering, splitting, etc. Has drastically changed the way I work. My PRs are undoubtably much better now, and I am never afraid of messing up thanks to jj undo and the op log in general
Do you have a public example of an open source project that you are using that showcases those features?
In your opinion, is jj losing steam? How do you feel about it requiring a CLA to contribute to, which would enable the developers to go closed-source and keep all the contributions of the community? Are you afraid of vendor lock-in?
> a public example of an open source project that you are using that showcases those features?
IMO that's almost fundamentally impossible. The whole point is that it makes maintaining a "clean" linear commit history easier than git, so by the time you push anything the observable differences are already gone. At best you just see a repo without any WIP-style commits, which can be done using more effort and git alone.
CLI is preferred from my point of view if only because it's the supported standard interface. VSCode's version control interface is reasonably close to a standard, and I love the tree view there. But generally I don't want to use random third party things because they either aren't consistent (i.e. now I have to learn what joe schmoe thinks a version control interface should be), or don't stick around long enough.
But I don't tell my team what they have to use as long as it's compatible. The last thing I want to do is try to teach them a different VCS when they've spent time learning how to get by with git.
I've told them about JJ, what I like, what pain points it solves for me. They are all adults, they can make their own decisions about it.
JJ is for me. It helps me unwind some rather elaborate problems we've had with rebasing, or dealing with conflicts from bringing some old support branch up to date, or back porting some particular thing. It helps me create pretty clean MRs, break things up into smaller reviewable chunks, etc. You can do all this with git, but it's easier in JJ. In particular if you have to do shuffling and rebasing and conflict arise. JJ lets you solve conflicts asynchronously to rebasing. Git stops you in your tracks. There's some rerere thing that is supposed to help but give me a break. Git's a train wreck of dumpster fires. But it's still been basically better than everything else since svn.
Until JJ IMHO. Valid arguments can be made for other things like maybe mercurial or even fossil. But JJ is the most pain-free vcs evolution I've seen.
Mercurial's big failing was making too many critical things optional. It's the same screw-up riscv is going through now in the chip architecture space.
A few advantages for me, even for the same 5 commands I use over and over:
- undo
- shuffling commits around with squash, split, and rebase is much better than git’s interactive rebase
- make commits without having to come up with a branch name (I might make three versions of the same change in parallel to see how they compare)
I see git is working on adding some of this under the history command. The revset language is really not esoteric: @ is head, @—- is two behind head. That’s about it.
Part of it is that the sorts of shuffling I used to avoid because they were a pain in git (so I didn’t feel I needed them improved) are so easy in jj that I do them all the time.
> - shuffling commits around with squash, split, and rebase is much better than git’s interactive rebase
Can you explain this to me? I feel like Git is pretty easy there.
- select oldest commit to modify
- move the commits around with a mouse or the cursor
- close the editor to apply
Sure, the first step can go away (which is what they do with git history), but the rest seems pretty optimal to me.
Alternatively I can add changes to older commits by recording them on top (--fixup) and tell git to auto apply them (--autosquash). I can also tell git to do the first thing automatically (git absorb, I believe it's inspired by jj).
It does take a few days to stop missing interactive rebase.
But say you’re in the middle of working on something and you wish you had a commit you made last week on an experimental branch on the current branch before the last commit you made. That’s jj rebase -r oldercommit --before @-, without interrupting your work. I don’t like to think about how I’d do that with git.
that’s the first example I’ve seen these last year so that makes sense to me about jj having better commit management.
I rebase a lot using Fork (git gui) and it’s really easy to drag and drop reorder commits, rename, apply as fixups or squash in. I can see how jj makes sense if you’re in the command line, though. And splitting changes from commits in git is really annoying, but it only comes up once in a blue moon for me.
The ability to rebase, reorder, and squash like this only really makes sense with jj’s autorebasing IMO.
With git, if you do this, everything after is left orphaned. Even if you have a GUI that does this for you, now rebase conflicts become an enormous pain.
> say you’re in the middle of working on something and you wish you had a commit you made last week on an experimental branch on the current branch before the last commit you made. That’s jj rebase -r oldercommit --before @-, without interrupting your work. I don’t like to think about how I’d do that with git.
This is the best pitch for jj I have seen yet. This should practically be the first text on their website.
How many of those do you need? How do find the correct arguments and git checkouts to do before? Are you sure you remembered to do everything? What if there are merge commits?
Why would I do a checkout before? I don't want to modify the worktree? Maybe I in fact also want to alter the worktree, but that's unrelated.
> Are you sure you remembered to do everything?
Am I sure I have all my files ordered? No. Does it matter? Also no. Are you sure you have no bug in your commits in JJ?
If I want git to alter some set of commit chains, I can tell it to. Actually I never needed to do that, because I don't work on several thousand branches at the same time. I prefer it to not alter unrelated branches automatically, just because some earlier commit changed that is in both. Such things actually undermines the trust I have in a tool, because it does things I haven't told it to do, even if I'm aware it does these things.
> What if there are merge commits?
Then I resolve them. Merge conflicts occur, because there is some actual conflicting change and often it is also semantic. These don't go a way by changing the VCS. On a theoretic basis, these require outside information(=decisions) that is not there yet. There are more often semantic conflicts, that are not syntactic, then there are the other way around. If you are referring to doing the same merge conflicts again, I can tell Git to resolve them automatically too, but it actually occurred too often, that this is not actually what I want, so I actually dislike that feature now.
I do, but I don't really get it, because you did learn the jj command. I mean you could have learned jj first, I would understand that, but I presume that is not the case.
jj just makes lots of git operations go from "technically possible if you're creative enough" to "<= 3 solutions, one of them probably being obvious". jj lowers the skill ceiling of git, and raises the floor.
Along with the appropriate git stash and git stash pops or git commit -anm wip and git reset HEAD^ so long as you’re not using your staging area for anything important, yeah.
Also if the cherry pick doesn’t cleanly apply at the current HEAD, you have to remember to either do the git rebase -i first and pause at the appropriate place to cherry pick if that works (I think it should?) or else start doing surgery because otherwise you’ll be resolving conflicts in two different directions as you cherry pick and then rebase and at that point I’m usually pulling up git reflog to try to find the last point where history made sense but I said I didn’t want to think about this.
> Along with the appropriate git stash and git stash pops
If you don't want to do that, you can tell git to do it automatically too? I actually thought I would like that, so I used it for a week. I did not like it at all.
> But if the cherry pick doesn’t cleanly apply at the current HEAD
If the diff you want to commit isn't applicable to the tree you want to apply it to, it's not going to work, no matter the VCS you use.
> then you have to remember to either do the git rebase -i first and pause at the appropriate place to cherry pick
You say that like these would be separate operations, but for me these are very much not, I guess like the fact that you need to supply both '-r oldercommit' and '--before @-' are for you. I think this is the point where I actually don't understand your view. Like, we both need to supply two parameters, we need to because this is the operation we want to do. You write two parameters free form, I write one free and select the other from a list. There is a difference, I actually think selecting from a list can be more convenient in some cases, less in others. But I don't get why you write like it would be crazy work.
> though I also recall rebase only letting you pause before a commit so you lose your commit message, but that’s probably a me problem
It does only let you handle full commits, if that's what you mean, if you want to split a commit you need to provide information how. But that it doesn't sound like you mean that.
> so you lose your commit message
You can apply commit metadata independently of the tree you want to commit, so that definitely occurs never.
> maybe detach your head
I bet you don't have issues with detaching the head in JJ, so why do you in Git, it's just a normal state.
> start doing surgery because otherwise you’ll be resolving conflicts in two different directions as you cherry pick and then rebase
Yes, but that is not because you use Git, but because you wrote the change against some other commit first, which you don't do in your JJ example. You could do that in Git as well and then you only have one set of merges to resolve.
> I’m usually going back to git reflog to try to find the last point where history made sense
Which is git rebase --abort or git reset @{1}. The latter is always the same, this is as silly as saying I can't remember whether it's jj undo or jj revert.
> But I said I didn’t want to think about this anymore.
If I may ask, how much time have you spent trying to learn use jj? I ask because I've seen a strong tendency for people to who have never used it to argue against it. I see much less arguments against it from people who understand both Git and jj well. But that's just my impression; I may of course be wrong.
Because it interferes with my workflow. If there are non-committed changes when I want to do something else, they do represent actions I want to do. I don't just have random uncommitted changes there. Setting --autosquash as default results in my finding out I forgot something later.
I believe this to be the same with the index, that is praised as unnecessary and "overcomed" in JJ.
I love the index, and often have "uncommitted" stuff lying around. jj makes doing this easier because you represent the index as an unnamed commit, and everything just works, as opposed to needing to manage the index vs committed changes with separate tools.
What I mean is, you manage the index with the same commands that you manage commits with.
I am super curious as to what you mean specifically, but I also know that getting into details can be annoying, so if you have some specifics I'd love to hear more about them. I loved git's index so this isn't coming from a place of "the index sucks and you shouldn't care about it" it's "I think jj executes the index better than git does actually". But also if you don't, that's fine by me too, if you like a tool you should continue to use it.
if you make commits, then you are at the scale where its killer features would shine. In other words, even the most basic git usage is made easier with jj.
If you care to learn more, there's tons of posts on hn and the broader web, so I won't bother sharing any links. I will say, though, that you should use it with jjui, which is a tremendous TUI for jj - you don't even really need to learn any of the actual jj syntax because it just handles it all for you.
Similar to you, 95% of the time I do the simple use case that I've memorized. The problem is that even after a decade of using Git, when I get into those 5% where something goes wrong, I have no idea how to actually solve it. None of it makes any sense in my head, and I have to search for a bunch of magical commands to run, or nuke things to get back to a good state.
With JJ, it just makes sense. It's intuitive and clear. I have been able to recover without any help. Just the undo alone is basically a life saver. Rebasing and merge conflict resolution is so much simpler.
Yes I probably won't use it to its full potential, but still, the little I do use makes 10x more sense than Git ever did.
I don’t know about you, but if you ever run git commit --amend, git rebase -i, git reset, git reset --hard, git stash, git add ., then these are all workflows that jujutsu makes easier and less error-prone.
I loved the staging area in git. That was the biggest thing that held me back from adopting jj for a long time, thinking it was a huge step backwards.
It wasn’t. I was wrong.
The staging area is just a commit like any other, only due to git’s design it has to be special-cased everywhere. In jj it’s just a commit.
I do all my work on an unnamed commit on the tip of a branch. As I complete bits, I extract out cohesive sets of changes into new commits (split) or as patches of earlier commits (squash).
Git is a DAG of commits, each of which is a node in the DAG. There's also a staging area that isn't a node in the DAG, and a working copy that also isn't a node in the DAG. The head nodes of every branch in the DAG are always named in git, and every node in the DAG also has a description. Nodes are immutable, but the edges between nodes are mutable so you can edit a node by replacing it with a new node & updating the edges.
JJ is a DAG of commits. Each commit is a node. Nodes have stable identifiers, automatically generated. Nodes may have descriptions. Nodes may also have names (bookmarks) which get used for compatibility with git's branch names. Nodes are mutable, but by default nodes pushed to a remote will be immutable.
I would (probably) not bother with jj if I only had to work on my own codebases. As a developer on an active repo with lots of contributors and ceremony around PR reviews (~500 lines per PR, stacks, etc.) it's invaluable.
222 comments
[ 0.22 ms ] story [ 18.9 ms ] thread(Martin joined back then, but we are posting about it today, so we should have the post date as today)
btw, did Martin leave google?
Do you have any idea if this is coming to jj soon?
Git has lots of implementations across lots of programming languages. No vendor lock-in is viable for git. Is vendor lock-in inevitable for jj? Git was started to not have to use a proprietary VCS.
> Git was created in April 2005 by Linus Torvalds, the creator of Linux. The Linux kernel project depended on BitKeeper, a proprietary distributed VCS. When a licensing dispute made BitKeeper unavailable for free, the project urgently needed an alternative.
The Google CLA is still required as of 2026, which I find strange. https://lwn.net/Articles/958805/
> Second, I thought about contributing a fix to that table, and then I saw the contributing requirements:
> > Contributor License Agreement
> Nope, not happening. Nobody should adopt this until it's been freed from that requirement, either by getting the project to remove it or by establishing a version of the project that takes contributions without that requirement.
Nobody wants to yet?
FWIW, while there aren't multiple reimplementations of the core yet, there ARE multiple GUI and wrapper projects that fulfill various needs, if you're just looking for outside contribution as a health measure.
- Gitoxide is 80,000+ lines of code.
- Git itself is over 170,000 lines of code.
- Even "Game of Trees" or "got" by the OpenBSD developers, which is a wholly separate project that has its own porcelain, is +120,000 LOC.
- Jujutsu itself is about 100,000 LOC.
- JGit for Java is around 200,000 LOC.
These are all roughly approximate and include things like testing code (but I think that's fair because tests are part of the project). All of these projects started small years ago, and are now large.
> If jj is not too complex to have multiple implementations, why have new implementations not sprung up by now?
"Make multiple implementations" is not, in and of itself, particularly valuable without some underlying justification to do so. It also is not how (AFAIK) any other version control system has ever worked; Git's "identity" as an on disk format is a particular design choice (with pros and cons), so yes you can get multiple tools with varying levels of features that agree on the basic disk format and poke at it. But most projects just don't work this way, much less other VCSs; there also aren't really many "Linux re-implementations" beyond toys because it is easier to just collectively contribute with each other, because Linux is not a "standard" written in stone, but a living and breathing thing.
[Emphasis from the source]
Does this make it possible for the jj organization to make the implementation closed-source and proprietary, and abandon the open source version, taking all the contributed changes from volunteers and other organizations with them?
There is no “the jj organization”.
But the thing is, Jujutsu is under the Apache 2.0 license right now. You are within your rights to use Apache 2.0 in proprietary products. Literally anyone, at this exact moment, could clone the repo and integrate it into a proprietary product, or share proprietary binaries built on the code (rename it Gugutsu VCS) without giving up the source, as long as they obey the ASL 2.0 terms. The CLA really has nothing to do with this fact.
If you are personally worried about your personal copyrighted patches going into proprietary products -- or if that's your only worry -- you basically need to avoid contributing to all projects that are not using a copyleft license; just avoiding CLAs or whatever isn't enough. This has been true for a while.
If you are worried about a "rug pull" the next question is whether the developers can actually do that. That is a matter of social configuration of the project, not licenses. The thing with "rug pull OSS projects" is mostly about ownership and labor. Licenses and CLAs really don't matter much if 99.8% of development comes from one group of unified engineers. Such a setup is risky even with a 0% chance of any license changes. Their company might fail or they might all get fired. You didn't get rug pulled, but the project might die, which is basically just as bad.
But for Jujutsu, there is no majority of developers from any one company, and significant amount of code comes from the community, so the answer is more or less "no, we can't do that even if we wanted." The best we could do is start a whole fork and lose a significant chunk of the community and contributors. There isn't any one group of people with enough of an iron grip to do that without sustaining massive losses.
I think people sort of get "Can this become proprietary", with "Is some <bad outcome> possible" -- in this case Jujutsu's code can absolutely "become" proprietary already in a real way. You can just go do that now. But a lot of "rug pull" things are prevented, I think, simply due to the fact we have a robust and strong community outside the (paid) developers
Ultimately, for a non-copyleft project, non-assigning CLAs like the one Jujutsu has are basically just annoying, legal ass covering mechanisms for Google's sake. I also do not like the CLA, it's just basically an irrelevant piece of paper in the grand scheme to me, though. The Linux kernel DCO is basically just a CLA with fewer words, motivated by similar concerns to not get backstabbed due to the business logic of suing people.
If we got rid of the CLA for Jujutsu, I personally think it would probably still be nice to ask people to respect the DCO.
If there's interest in alternative implementations, then they'll happen, simple as that. The reason it hasn't happened is that there isn't any desire for one.
I wonder how guaranteed that is, can imagine GH deciding to 'clean' it (how much data can you put there theoretically? Or to close a range of potential security issues) and suddenly relatively niche but genuine uses like jj's change-id are unintentionally not preserved.
Not really. I remember my early years with git and the favt was that I never needed more than clone, add, commit, pull and push. While I’ve done some mistakes that got ne to learn more, especially with creating branches and undoing. I’ve never needed a lot, even when I started using GUI which exposed more concepts.
Why? Because I have no understanding of version management and how it’s useful in a dev workflow/release process. I was just using it for checking in work.
Since then, I’ve read the “Pro Git” book, learned how devs and teams handle versioning and devel a good understanding of how git can help me in my coding process and general software development. And it’s very good at what it does.
At the team level, it’s guided by the release process, configuration management, which version is canonical. At the programmer level, it’s usually guided by how to switch between task, how easy to explore an idea and save the resulting experiment, how to reset the code to a know state and how to replay a previous changes on top of new changes.
So you discern what you want to do (which is independent of the tool), the learn how to use git to do them. If you start from git, you’re going to be confused, just like someone opening autocad with no knowledge of engineering drawing.
Git is quite powerful, but the cli is a train wreck of complexity and inconsistency. Learning the options to one git command means you’ve learned the options to exactly one git command. No other git command is required to use the same terminology. Personally, I was stuck in “git basics land” (all the basic commands you list) until I adopted Magit in Emacs. IMO, the Magit team deserves a medal for making git usable at an advanced level.
I don’t have an opinion about jj yet, but no one can hold up git as a pinnacle of great source control. Yes, it’s powerful, but it’s a UI train wreck.
You forgot the “because it's actually kind of terrible from a UX standpoint”. My stance is against that. I haven’t learned git in depth because I never knew any other workflow than code and check in the changes. There’s not a lot of guides on how version control can help in the software development process.
It wasn’t until I got involved into OSS that I learned more which in turns give me the motivation to use and learn about git in depth. I’m also using magit (after a tour in various GUI) but for me it is to git what vi is to ex. Direct interaction instead of a command prompt.
I'm not sure I understand how "I use a specific text editor with a specialized interface into git that's superior" is a counterargument to the first-party tool having horrible UX. That seems basically the exact same as what I was saying about jj, except via emacs instead of a CLI. Either way, we've opted out of the actual experience of the tool in favor of using an alternative tool that operates on the version control.
It requires the same mental model as git.
The repository is a store, you check out the previously saved instance of a file, a group of files, or a subtree. In that regards, switching branches and restoring files is actually the same thing. A commit stores whole files and branches are pointers to commits (which update themeselves).
Maybe you can explain how is it leaky based on your understanding of version control?
I also have used plenty of SCM systems since mid-90's.
They have less to walk away from then.
TBH learning git in depth was a hindrance for me learning jj - for my first few weeks I kept instinctively looking for complex solutions to simple problems and being confused, when the answer was always "use the tools you already know"
As a concrete example - git has one set of commands for managing commits, a different set of commands for managing the index, a third set of commands for managing stashes, a fourth set of commands for managing the working directory, and a fifth set of commands for managing conflicts -- in jj all of those things are a single concept with a single set of commands, equally (if not more) powerful, but also simpler
We liked our old look, but one funny thing about how things are going in the world: our old color scheme was too close to what happens when you ask Claude to generate a site, and so even though we paid a human to build it, we didn't want to communicate slop, especially because that's not what we did!
Nick Noble is our designer, he put in a bunch of work on this, and I really like it too.
There will be a lot more of it soon :D
Small hint: A moving background layer makes reading supremely annoying, and for some people even virtually impossible.
Any other reccs?
I wrote about why I joined the company back when I did previously here: https://steveklabnik.com/writing/i-see-a-future-in-jj/
In short: we are building a next generation source control system for the enterprise.
We have git.
jujutsu works with git.
git can do everything jujutsu can do (otherwise, jujutsu couldn't work with git).
Thus, jujutsu is a UX / new steering wheel.
ERSC is trying to be a GitHub competitor with what surplus value?
Don't get me wrong, GitHub has a slew of its own problems, but I have not seen any commentary on how ERSC addresses any of the downfalls GitHub has too. We're jumping from one frying pan into another, currently-cooler one?
What about SourceHut? Codeberg? They could offer the same steering wheels.
If I had to guess, then I would say ERSC is trying to build a `jj` forge based on this new hire and that would be amazing imo.
While jj works with git, it doesn't have to. jj has the ability to work with many backends. Git is the popular one in the open source world, but that doesn't mean that other ones are not possible. And that's the core tech we have built.
With the rise of agents, more and more companies are running into the limits of what Git can do. It was never designed for large monorepos, and so there are performance issues, but also features that it's missing, that are important once you start trying to scale things up to an entire organization. Companies like Meta and Google ran into these things well before the present moment, but you don't have to be a FAANG these days to be running into this sort of stuff.
We also understand that incremental adoption is really important, especially for something as fundamental as source control. So our tech also has a git ingress/egress that will work with the core functionality, but more advanced things that git simply can't do will end up requiring using a non-git protocol. jj is the bridge between those two worlds.
I hope that makes sense! We have been in psudeo-stealth for a while now, this is the start of us coming out of our shell a bit and actually talking about what we're doing.
You mention performance issues with Git, but there are performance issues with this blog post.
No one has agreed to this premise. You have invented it out of nowhere.
I’m not saying not to try or that there’s no value in turning the wheel once more. But I used to be excited about these kinds of things and now I’m not because I’ve seen the cycle a few times now.
But there are so many hooks into the Git workflow today, and I’m struggling to find a “user story” that would not be met by custom Git tooling. UX could be added to Git objects à la Gerrit with custom CLIs, custom Gitoxide ODB and (eventually) ref storage backends can help the server scale, and things like promisor remotes and partial clones can keep things smaller on the client side.
I’m curious what ERSC is able to share publicly about where the scaling fails with the Git specification? Is it the wire format, or the relative speed of upstreaming new things to Git? Or is the side-channel approach for storing rich data in Git objects insufficient in some way?
P.S. I wrote a blog post[1] about this a bit ago. I’m sure I’m missing something. Since I wrote it, I’ve wondered if the lack of deferred conflicts in-tree would be a scaling limiter.
[1] https://jdc.pub/posts/git-jj
Yes, it's important to realize that git is multiple things: the on-disk repo format, the CLI, and the wire protocol. Each has their own challenges, just like any project, but they can be tackled independently. But at the end of the day, there just are fundamental limits to the way that git does things that make total sense in the context Linus developed git for, but just do not in other ones. Some of those are performance related, but some of those are things like how the kernel is an open source project, and so per-directory ACLs are something that git wouldn't ever bother supporting, but are valuable for companies. We'll be talking about these things in the future, so I'm just going to be hand-wavy about it right now. But we do think that git is a really great system that has served us all well for 20 years, but just like how git displaced systems before it due to significantly re-thinking the details, for some users, making meaningful improvements over git will also require a similar significant re-think. That's just the way of technological development.
Initially we won't be offering our own CI directly, you'll bring your own. We use Buildkite internally, so we'll probably share that integration first, but fundamentally you can do whatever you'd like. We won't require you to use whatever first-party offering we end up with.
I don't know how experienced you are with jj, but one thing I can say for sure is jj offers significant ux improvements over git and they plan to have a backend eventually. we might see the first implementation from ersc. and from their website I see they are already taking things like agents into account from day one. so we might be in the verge of getting something that scales better with modern day workload?
FWIW I think it's a bit more nuanced than that. As a trivial counter example Git does not currently have a way to store conflicts inside commits[1], which is one of our major features. The way this works is that we basically store the sides of the conflicting trees in the Git object database (and another conflicted tree pointing to all of them), but the actual data structure representing the conflict as Jujutsu understands it is stored elsewhere. Git will be very confused looking at a conflicted tree object created by Jujutsu -- it shouldn't break but it doesn't understand what it's seeing. So, if a object can be stored in the database that is correct but Git can't really "view" it properly, does "git" (or capital-G Git) support it or not? Depends on who you ask, I guess. The storage layout being intimately tied to Git "as a thing", part of its identity, is one of the most interesting properties it has.
The way I see it is this. Jujutsu uses the Git storage layout on disk. But basically all of the algorithms and UX between the two are completely different. That is where most of the real differences are. To the extent we integrate with lots of fiddly Git details (eg tracking branches, remote integration etc) so that `git` commands work -- that's more necessity to make the UX nice. We could absolutely use the on disk Git format but in a way that was inscrutible to the `git` CLI, it just obviously would not be very nice.
As a disclosure I work at ERSC but I am also one of the maintainers of Jujutsu; this post is written with my maintainer hat on.
[1] At Git Merge last year, Elijah Newren prototyped and demo'd a really early and cool example of storing first class conflicts in Git, based on his work on ort-merge. So this might not be true forever :)
Yes, I like how jj does it!
Did a big `git rebase -i` yesterday and I felt stressed up, almost a bit angry, when there were some conflicts and I wasn't sure if I'd resolve all of them before it was time to leave, and work more later from a different laptop.
But with jj, no stress: I can just check in the conflicts, and later, on the other laptop: check out the conflicts and continue resolving.
(I just wish there was Git submodule support :- ))
I use JJ locally and for those that call it a "porcelain" or a "git UI" are missing a lot. Sure you can use it that way, but what I've found is that it facilitates (and perhaps encourages) a pretty different workflow than I'd use with just plain Git. I could pull off what I do in JJ in just plain Git... but it wouldn't at all feel natural and you can really see this when you start using a JJ driven repository with Git tools (including just the Git command line tools).
Personally, and as a mere version control user, I prefer the JJ model of version control much more than Git's. The mechanics of the UI was very easy to get under my fingers (the essentials in about a day), but getting the ideas and really getting an understanding/appreciation for the conceptual differences and their ramifications on workflow took a month or two of regular working and trying things. For me, it was worth the effort.
Just like TypeScript with JS, QUIC with UDP, GraphQL with HTTP, Android with Linux, and so on
> git can do everything jujutsu can do (otherwise, jujutsu couldn't work with git)
Replace "jujutsu"/"git" by "typescript"/"js", "quic/udp", etc and you'll understand.
assembly can do everything [insert high level language] can do. why not just write everything in that?
If you haven't tried jj yet, take it for a spin and see how you like it.
jj's data store is git. You can use jj while other people on your project just use git. There's no migration of data or history. You can use Github and all of the various git tooling that exists today.
As such, the initial cost of switching to jj is zero for individuals, teams, or projects. That's huge.
jj's ergonomics are significantly nicer. Fewer ways to shoot yourself in the foot, much better merge resolution, etc.
Where can I read on jj merge resolution strategies? LLM links to Arch Linux man page and other random stuff.
The jj tutorial is useful: https://docs.jj-vcs.dev/latest/tutorial/
It doesn't sound like much, but before I started contributing to Jujutsu I was a user of https://sapling-scm.com/ -- Sapling is fantastic. It stores data on disk in git format, but back then it was not exposed to the user by default -- the .git directory is hidden away. It actually ended up causing a lot of friction that random `git` commands would not work, or tools had other various git-based behaviors. These days, sapling has a "dotgit" mode (partially inspired by jj I assume) that puts the .git directory in the root dir, so `git` commands still work.
Beyond that though, speaking Git over the network only has other complications on the client side. In particular Git clients and servers negotiate what objects each side has (given what the client requests), and from that negotiation derives a list of needed objects to give the client, and then sends a packfile for it. This is all relatively expensive to do on demand, actually, so it would make the interactivity for network operations much worse if you need to wholly translate your storage into packed objects, etc. And doing it efficiently would require you keeping a cache around that is basically a git database anyway, so you might as well just go ahead and use it. Not the end of the world in terms of downsides, but a trade-off that adds some baggage.
There's no network effect headwinds, it's interoperable with git (I assume most people using jj have an upstream repo that's on git).
I have only played a little with jj and hg, but I felt that jj has a more modern UX, learning from years of Git existence (and even influencing Git, like the new `git history` command [1]). On the other hand, hg was created in the same month as Git, both trying to improve the experience of the VCSs available at the time (april 2005).
[1] https://lore.kernel.org/git/20250819-b4-pks-history-builtin-...
jj borrowed quite a few things from mercurial.
So, jj can be thought at least partially as a spiritual successor. Meta's Sapling is in a similar position. From this perspective, the key feature of both is transparent git repo and git remote support (hg can speak git as a foreign language, but it's limited)
And if your muscle memory doesn't allow an immediate transition, give yourself 2 weeks. That's how long it took for me at least.
Invest in custom tooling and helper scripts.
Looking forward to using the VCS stuff you'll create :- )
We should be respecting https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/A... . If we do not, that's a bug, and please let me know what browser/OS/whatever else combo you have if that is an issue.
love the website though, i hope i one day will be able to make something that elegant!
For anyone curious the big thing with jj is you can undo. Basically if you were running a rebase and bungled a commit sha or branch name, no worries undo your way out, if you forgot to push but abandoned a commit not issues undo it. Same with all jj commands.
Delta db takes this a step further and everything you edit is a change so your actual edits are also all saved.
I find non destructive-ness for as long as possible approach very nice, since there aren't as many constraints on us not being able to do it nowadays, we had limited storage and stuff in 2000s perhaps but in 2026 even with the killer SSD prices it's fairly cheap to buy more SSD, we can definitely waste 100MB per project storing redundant history we may not ever need.
Same way in photoshop non destructive editing took over, especially useful for humans, but works for AI and LLMs too, they can undo their mistakes as well.
¹ https://drive.google.com/file/d/1dVzug1lHoOxdbFu8gcCJCu-G_uV...
Points of no return.
You worked on multiple things, you sync with the upstream, then boom now you have conflicts in one or more of your local branches.
Instead of immediately presenting you a conflict resolution view (usually 3 pane vimdiff) and you'll have to resolve at the sync time, the commits are simply marked as "have conflict", and you can continue working on other things until you have time to deal with it.
And for a chain of commits that all have conflicts, chances are fixing the first conflict automatically resolves all other conflicts in the chain, thanks to the auto-rebasing feature.
2. Yeah submodules aren't supported but since you can use jj in a git repo you can commit git stuff via git like submodules and then enjoy the world of jj. Since submodule interactions should be rare imho. I use it for a bunch of projects with submodules.
For instance, if you are interactively using `git bisect` and you mark commits as good or bad, and you accidentally mark a commit incorrectly, you have to do something like:
The reflog can't really capture this kind of thing, hence why you have a bisect log -- now a wholly separate concept that exists independently of the reflog.[1]Another example is when you do something like screw up an interactive rebase. Let's say you rebase 20 commits and then you get a conflict on commit 8. You fix the file conflicts, and continue. You accidentally solve the merge incorrectly, continue and get another conflict -- but only realize your mistake after you start solving it. The reflog can't save you here. You have to completely abandon the rebase and start over. (This specific example might be handled better these days).
I think the biggest thing about `jj undo` is that it works everywhere. You can undo rebases, merges, conflict resolutions, copies, deletions, whatever. The secret behind it all is that internally, jj is architected in a way where implementing a feature looks like you are working with a transactional database. You actually have `begin_transaction()` and `commit()` methods in the codebase that will make changes to the commit graph visible in an atomic way. When a command like `jj rebase` happens, all of the changes it makes are inside a transaction and committed at once. Every operation in the repo is a transaction, and it all goes into a log, which records the effects of a transaction -- very much like a database system!
So "undo" just means "undo the effects recorded in a transaction" and that is about all. And so it works for everything! And this design is very easy to intuitively understand and program against, as a maintainer, along with our other high level internal APIs. Any developer can easily write code that Just Does The Right Thing and the user can undo it and it's no big deal. When I develop and work on Jujutsu myself -- like I'm actively developing new features or prototyping ideas -- I almost always _my own jj repository_ as a test repo while testing my builds.
In contrast, Git does not have one unified "transactional" layer for things like this. But not all is lost, there has been work on 'git undo' and it was implemented by... Someone who is now a Jujutsu maintainer[2]. :)
[1] Technically we do not yet have "step by step" bisect with good/bad yet (only "automatic" bisect that is one-shot), so that is something Git can do we can't do at all right now, but bear with me. :')
[2] https://blog.waleedkhan.name/git-undo/
Since jj snapshots the commit you're editing a lot, you can often even jj undo an accidental edit to a just-created file that in git would have still been uncommitted.
Most of the maintainer stuff is also overhyped in a way (OSS maintainer-heads know this). The maintainer group is largely structured to just keep things moving; not really a privilege but a responsibility -- making sure things get merged, doing technical reviews, ensure builds are unstuck, and hitting the green approval button. Our own community members also do code review, find bugs, triage things, answer questions, help get users unstuck, etc. We are very much not alone, and I have great confidence in the constitution and strength of the community itself as someone who has been around the block a few times.
This is going to sound silly and "guy approves of himself" adjacent, but I've been doing OSS maintainer stuff for like 2 decades at this point, and jj is truly a gem as a project. It is vibrant, and the community is generally speaking insanely talented (huge number of git powerusers), and we have a weird dogfood advantage where people use the tool to contribute right back to it. Martin did an awesome job setting the tone of the project just through his behavior before many of us joined years ago.
As I said elsewhere: I work for ERSC and I am a Jujutsu maintainer. This is just me speaking candidly on my own behalf.
The things I am most interested in right now are jj and llms. And the intersection between the two. I'm thinking a lot these days about how agentic development is changing our industry, with source control being one part of that.
Is it the animation at the top?
Edit: what system / browser are you on?
JJ is just so low friction. The seamless and painless shuffling of commits, working up and down the commit chain without explicit rebasing, unchanging change-ids. The min identifiers in change-ids being highlighted. Being able to make commits and worry about the message later. Snapshots of changes while you are working serving as a tool agnostic undo.
Painless and sensible cli args that are vastly more consistent than git.
Superior conflict handling.
You can “jj undo” anything and it works perfectly.
It’s fabulous.
> "@--+::"
I have no idea what that means and I’ve never had to type anything remotely like it.
The rev specification language is pretty elaborate but you don’t need to know it.
Marketing push on Hacker News and elsewhere aside, jj also has the issue that it does not seem to have multiple implementations in multiple languages. In the current top thread, https://news.ycombinator.com/item?id=49527748 , people argue in favor of both Firefox, Ladybird, Servo, et cetera, such that they are not bound to one vendor and one implementation. Git has multiple implementations across multiple languages, entirely appropriate for core infrastructure like VCS. Where is the C or second Rust implementation of jj? And if there is only one implementation of jj, is jj appropriate for usage as a VCS?
Is jj too complicated to have multiple implementations?
In your opinion, is jj losing steam? How do you feel about it requiring a CLA to contribute to, which would enable the developers to go closed-source and keep all the contributions of the community? Are you afraid of vendor lock-in?
IMO that's almost fundamentally impossible. The whole point is that it makes maintaining a "clean" linear commit history easier than git, so by the time you push anything the observable differences are already gone. At best you just see a repo without any WIP-style commits, which can be done using more effort and git alone.
Or if it were a family tree, "all descendants of your children and their cousins" (ignoring that family trees are way more constrained than DAGs).
I have no idea why you would use that revset; I assumed it was just an example of revset's complexity and power.
As a pragmatic matter, unless I'm scripting with revsets, I personally stick to a few go-to aliases.
But I don't tell my team what they have to use as long as it's compatible. The last thing I want to do is try to teach them a different VCS when they've spent time learning how to get by with git.
I've told them about JJ, what I like, what pain points it solves for me. They are all adults, they can make their own decisions about it.
JJ is for me. It helps me unwind some rather elaborate problems we've had with rebasing, or dealing with conflicts from bringing some old support branch up to date, or back porting some particular thing. It helps me create pretty clean MRs, break things up into smaller reviewable chunks, etc. You can do all this with git, but it's easier in JJ. In particular if you have to do shuffling and rebasing and conflict arise. JJ lets you solve conflicts asynchronously to rebasing. Git stops you in your tracks. There's some rerere thing that is supposed to help but give me a break. Git's a train wreck of dumpster fires. But it's still been basically better than everything else since svn.
Until JJ IMHO. Valid arguments can be made for other things like maybe mercurial or even fossil. But JJ is the most pain-free vcs evolution I've seen.
Mercurial's big failing was making too many critical things optional. It's the same screw-up riscv is going through now in the chip architecture space.
- undo
- shuffling commits around with squash, split, and rebase is much better than git’s interactive rebase
- make commits without having to come up with a branch name (I might make three versions of the same change in parallel to see how they compare)
I see git is working on adding some of this under the history command. The revset language is really not esoteric: @ is head, @—- is two behind head. That’s about it.
Part of it is that the sorts of shuffling I used to avoid because they were a pain in git (so I didn’t feel I needed them improved) are so easy in jj that I do them all the time.
Can you explain this to me? I feel like Git is pretty easy there.
Sure, the first step can go away (which is what they do with git history), but the rest seems pretty optimal to me.Alternatively I can add changes to older commits by recording them on top (--fixup) and tell git to auto apply them (--autosquash). I can also tell git to do the first thing automatically (git absorb, I believe it's inspired by jj).
But say you’re in the middle of working on something and you wish you had a commit you made last week on an experimental branch on the current branch before the last commit you made. That’s jj rebase -r oldercommit --before @-, without interrupting your work. I don’t like to think about how I’d do that with git.
I rebase a lot using Fork (git gui) and it’s really easy to drag and drop reorder commits, rename, apply as fixups or squash in. I can see how jj makes sense if you’re in the command line, though. And splitting changes from commits in git is really annoying, but it only comes up once in a blue moon for me.
With git, if you do this, everything after is left orphaned. Even if you have a GUI that does this for you, now rebase conflicts become an enormous pain.
This is the best pitch for jj I have seen yet. This should practically be the first text on their website.
All of that is automatic with jj.
How many do I want?
> How do find the correct arguments
How do you find the correct arguments for jj?
> and git checkouts to do before?
Why would I do a checkout before? I don't want to modify the worktree? Maybe I in fact also want to alter the worktree, but that's unrelated.
> Are you sure you remembered to do everything?
Am I sure I have all my files ordered? No. Does it matter? Also no. Are you sure you have no bug in your commits in JJ?
If I want git to alter some set of commit chains, I can tell it to. Actually I never needed to do that, because I don't work on several thousand branches at the same time. I prefer it to not alter unrelated branches automatically, just because some earlier commit changed that is in both. Such things actually undermines the trust I have in a tool, because it does things I haven't told it to do, even if I'm aware it does these things.
> What if there are merge commits?
Then I resolve them. Merge conflicts occur, because there is some actual conflicting change and often it is also semantic. These don't go a way by changing the VCS. On a theoretic basis, these require outside information(=decisions) that is not there yet. There are more often semantic conflicts, that are not syntactic, then there are the other way around. If you are referring to doing the same merge conflicts again, I can tell Git to resolve them automatically too, but it actually occurred too often, that this is not actually what I want, so I actually dislike that feature now.
git cherry-pick + git rebase -i (to swap commit order)?
?
Also if the cherry pick doesn’t cleanly apply at the current HEAD, you have to remember to either do the git rebase -i first and pause at the appropriate place to cherry pick if that works (I think it should?) or else start doing surgery because otherwise you’ll be resolving conflicts in two different directions as you cherry pick and then rebase and at that point I’m usually pulling up git reflog to try to find the last point where history made sense but I said I didn’t want to think about this.
If you don't want to do that, you can tell git to do it automatically too? I actually thought I would like that, so I used it for a week. I did not like it at all.
> But if the cherry pick doesn’t cleanly apply at the current HEAD
If the diff you want to commit isn't applicable to the tree you want to apply it to, it's not going to work, no matter the VCS you use.
> then you have to remember to either do the git rebase -i first and pause at the appropriate place to cherry pick
You say that like these would be separate operations, but for me these are very much not, I guess like the fact that you need to supply both '-r oldercommit' and '--before @-' are for you. I think this is the point where I actually don't understand your view. Like, we both need to supply two parameters, we need to because this is the operation we want to do. You write two parameters free form, I write one free and select the other from a list. There is a difference, I actually think selecting from a list can be more convenient in some cases, less in others. But I don't get why you write like it would be crazy work.
> though I also recall rebase only letting you pause before a commit so you lose your commit message, but that’s probably a me problem
It does only let you handle full commits, if that's what you mean, if you want to split a commit you need to provide information how. But that it doesn't sound like you mean that.
> so you lose your commit message
You can apply commit metadata independently of the tree you want to commit, so that definitely occurs never.
> maybe detach your head
I bet you don't have issues with detaching the head in JJ, so why do you in Git, it's just a normal state.
> start doing surgery because otherwise you’ll be resolving conflicts in two different directions as you cherry pick and then rebase
Yes, but that is not because you use Git, but because you wrote the change against some other commit first, which you don't do in your JJ example. You could do that in Git as well and then you only have one set of merges to resolve.
> I’m usually going back to git reflog to try to find the last point where history made sense
Which is git rebase --abort or git reset @{1}. The latter is always the same, this is as silly as saying I can't remember whether it's jj undo or jj revert.
> But I said I didn’t want to think about this anymore.
Yet you do in JJ.
Because it left you fewer opportunities to experience the ecstasy of typing git commands into a terminal? Or because it didn't work so well?
I believe this to be the same with the index, that is praised as unnecessary and "overcomed" in JJ.
I am super curious as to what you mean specifically, but I also know that getting into details can be annoying, so if you have some specifics I'd love to hear more about them. I loved git's index so this isn't coming from a place of "the index sucks and you shouldn't care about it" it's "I think jj executes the index better than git does actually". But also if you don't, that's fine by me too, if you like a tool you should continue to use it.
(I never set autosquash either)
https://lottia.net/notes/0013-git-jujutsu-miniature.html
If you care to learn more, there's tons of posts on hn and the broader web, so I won't bother sharing any links. I will say, though, that you should use it with jjui, which is a tremendous TUI for jj - you don't even really need to learn any of the actual jj syntax because it just handles it all for you.
https://github.com/idursun/jjui
Similar to you, 95% of the time I do the simple use case that I've memorized. The problem is that even after a decade of using Git, when I get into those 5% where something goes wrong, I have no idea how to actually solve it. None of it makes any sense in my head, and I have to search for a bunch of magical commands to run, or nuke things to get back to a good state.
With JJ, it just makes sense. It's intuitive and clear. I have been able to recover without any help. Just the undo alone is basically a life saver. Rebasing and merge conflict resolution is so much simpler.
Yes I probably won't use it to its full potential, but still, the little I do use makes 10x more sense than Git ever did.
It wasn’t. I was wrong.
The staging area is just a commit like any other, only due to git’s design it has to be special-cased everywhere. In jj it’s just a commit.
I do all my work on an unnamed commit on the tip of a branch. As I complete bits, I extract out cohesive sets of changes into new commits (split) or as patches of earlier commits (squash).
Git is a DAG of commits, each of which is a node in the DAG. There's also a staging area that isn't a node in the DAG, and a working copy that also isn't a node in the DAG. The head nodes of every branch in the DAG are always named in git, and every node in the DAG also has a description. Nodes are immutable, but the edges between nodes are mutable so you can edit a node by replacing it with a new node & updating the edges.
JJ is a DAG of commits. Each commit is a node. Nodes have stable identifiers, automatically generated. Nodes may have descriptions. Nodes may also have names (bookmarks) which get used for compatibility with git's branch names. Nodes are mutable, but by default nodes pushed to a remote will be immutable.