Remix.run Logo
Jujutsu megamerges for fun and profit(isaaccorbrey.com)
262 points by icorbrey 2 days ago | 172 comments
umvi 2 days ago | parent | next [-]

I don't get JJ. Every time it's posted people gush about how JJ enables some super complicated workflow that I can't wrap my head around. I have a simple feature branch/rebase workflow in git that has served me well for decades so I guess I don't understand why I would want to complicate things with (in this case) an "octopus merge/megamerge". Wouldn't that make it more difficult to reason about the repository/history?

surajrmal 2 days ago | parent | next [-]

If you wrangle a lot of in flight changes that are not yet merged into your teams primary git repo, it's very helpful. I have some 10-30 changes in various states at any time. Sometimes they have dependencies on each other sometimes they don't. Placing them all into one branch can work but it's a lot less ergonomic in many ways. jj makes my life simpler because it accommodates my workflow in a way git doesn't.

Honestly, if you don't find it appealing you don't need to use it. I think a lot of folks don't find vim appealing and stick to vscode and that's okay too.

locknitpicker 2 days ago | parent | next [-]

> I have some 10-30 changes in various states at any time. Sometimes they have dependencies on each other sometimes they don't.

This is the sort of scenario that leans me towards thinking tools are being praised by how they support major red flags in development flows.

Having dozens of changes in flight in feature branches that may or may not be interdependent is a major red flag. Claiming that a tool simplifies managing this sort of workflow sounds like you are mitigating a problem whose root cause is something else.

To me it reads like praising a tool for how it streamlines deployments to production by skipping all tests and deployment steps. I mean, sure. But doesn't this mask a far bigger problem? Why would anyone feel the need to skip checks and guardrails?

seba_dos1 2 days ago | parent | next [-]

Some will say that it's a "red flag", others will say that those saying it's a red flag lack the experience of working on diverse set of projects with various needs and requirements.

locknitpicker a day ago | parent [-]

> Some will say that it's a "red flag", others will say that those saying it's a red flag lack the experience of working on diverse set of projects with various needs and requirements.

What if those who call out red flags actually do so based on experience,particularly in understanding how and why red flags are red flags and why it's counterproductive to create your own problems?

I mean, if after all your rich experience working on diverse set of projects with various needs and requirements, your answer to repeatedly shooting yourself in the foot is that you need a tool to better aim around your toes... What does it say about what lessons you draw?

SAI_Peregrinus 2 days ago | parent | prev [-]

Take Linux: they've got a "super-long-term-support" branch, a "long-term-support" branch, a "stable" branch, and the next "stable" branch. Stable is supported until the release of the next "stable" & 3 months after that, with (usually) 2-6 months between stable releases. "long-term-support" branches are supported for about 5 years, "super-long-term-support" for a few years after that. So there can be up to 4 released branches actively supported at any given time, ignoring any feature branches.

SOLAR_FIELDS 2 days ago | parent | prev [-]

Every time I hear about this megamerge and stacked pr nonsense, it just smells to me. Like, why does your engineering organization have a culture where this sort of nonsense is required in the first place? Anytime I see articles like this gushing about how great tool XYZ is for stack merging and things like that, all I hear is "you don't have a culture where you can get someone looking at and mainlining your PR on the same day"

The jj lovers can go build their massive beautiful branches off in a corner, I'll be over here building an SDLC that doesn't require that.

Old man yells at cloud moment is over

chrishill89 2 days ago | parent | next [-]

Not all software is developed by one software organization.

Programs to manage “stacks of patches” go back decades. That might be hundreds that have accumulated over years which are all rebased on the upstream repository. The upstream repository might be someone you barely know, or someone you haven’t managed to get a response from. But you have your changes in your fork and you need to maintain it yourself until upstream accepts it (if they ever call back).

I’m pretty sure that the Git For Windows project is managed as patches on top of Git. And I’ve seen the maintainer post patches to the Git mailing list saying something like, okay we’ve been using this for months now and I think it’s time that it is incorporated in Git.[1]

I’ve seen patches posted to the Git mailing list where they talk about how this new thing (like a command) was originally developed by someone on GitHub (say) but now someone on GitLab (say) took it over and wants to upstream it. Maybe years after it was started.

Almost all changes to the Git project need to incubate for a week in an integration branch called `next` before it is merged to `master`.[1] Beyond slow testing for Git project itself, this means that downstream projects can use `next` in their automated testing to catch regressions before they hit `master`.

† 1: Which is kind of a like a “megamerge”

SOLAR_FIELDS 2 days ago | parent | next [-]

Makes total sense! But what you described is like less than 5% of the use case here. Right tool for the right job and all that, what doesn't make sense is having this insanity in a "normal" software engineering setup where a single company owns and maintains the codebase, which is the vast majority of use cases.

chrishill89 2 days ago | parent | prev | next [-]

> incorporated in Git.[1]

Dangling footnote. I decided against adding one and forgot to remove it.

2 days ago | parent [-]
[deleted]
2 days ago | parent | prev [-]
[deleted]
surajrmal 2 days ago | parent | prev | next [-]

It depends. We have pretty good review culture (usually same day rarely more than 24H), but some changes may need multiple rounds of review or might be have flaky tests that uncovers after a few hours. Also some work is experimental and not ready for pushing out for review. Sometimes I create a very large number of commits as part of a migration DND I can't get them all reviewed in parallel. It can be a lot of things. Maybe it happens more with monorepos.

SOLAR_FIELDS 2 days ago | parent [-]

All fair points, indeed I face each of the challenges you listed periodically myself. But it's never been often enough to feel like I need to seek out an entirely different toolchain and approach to manage them.

dwb 2 days ago | parent [-]

Well, fortunately Jujutsu isn’t an entirely different toolchain and/or approach. It’s one tool that’s git-compatible and is quite similar to it. But where it’s different, it’s (for me) better.

seba_dos1 2 days ago | parent [-]

Yeah, I've never used Jujutsu, but from what I've seen so far everything it does can be done with Git itself, just perhaps in a (sometimes significantly) less convenient way.

dwb 2 days ago | parent [-]

Sure, true, I would say "often significantly" though, to the extent that you would never bother doing half the things with git that you can do with Jujutsu because it's such a pain.

mi_lk 2 days ago | parent | prev | next [-]

I'd really like to hear your argument about when single large PR is better than stacked PRs from both PR author and reviewers' perspectives

SOLAR_FIELDS 2 days ago | parent [-]

Why frame this as either/or? Those aren't the only two options.

There are different types of "large" PR's. If I'm doing a 10,000 LOC refactor that's changing a method signature, that's a "large" PR, but who cares? It's the same thing being done over and over, I get a gist of the approach, do some sampling and sanity checks, check sensitive areas, and done.

If I'm doing something more complex and storied to the point it requires stacks with dependencies, then I'm questioning why I haven't split and chunked the thing into smaller PR's in the first place and having those reviewed. Ultimately the code still has to get reviewed, so often it's about reframing the mindset more than anything else. If it organizationally slows me down to the point that chunking the PR into smaller components is worse than a stacked-pr like approach, I'm not questioning the PR structure, I'm questioning why I'm being slowed down organizationally. Are my reviews not picked up fast enough? Is the automated testing situation not good enough? The answer always seems to come back to the process and not the tooling in these scenarios.

What problem does the stacked PR solve? It's so I can continue working downstream while someone else reviews my unmainlined upstream code that it depends on. If my upstream code gets mainlined at a reasonable rate, why is this even a problem to be solved? It also implies that you're only managing 1-3 major workstreams if you're getting blocked on the feature downstream which also begs the question, why am I waterfalling all of my work like this?

Fundamentally, I still have to manage the dependency issue with upstream PR's, even when I'm using stacked PR's. Let's say that an upstream reviewer in my stacked PR chain needs me to change something significant - a fairly normal operation in the course of review. I still have to walk down that chain and update my code accordingly. Having tools to slightly make that easier is nice, but the cost benefit of being on a different opt in toolchain that requires its own learning curve is questionable.

mi_lk a day ago | parent [-]

> If I'm doing something more complex and storied to the point it requires stacks with dependencies, then I'm questioning why I haven't split and chunked the thing into smaller PR's in the first place and having those reviewed.

It looks like you see stack PR as an inherent complex construct, but IMO splitting the implementation into smaller, more digestable and self-contained PRs is what stack PR is about

So if you agree that is a better engineering practice, then jj is only a tool that helps you do that without thinking too much about the tool itself

baq 2 days ago | parent | prev | next [-]

Why would you like git and not jj is beyond me, this must be something like two electric charges being the same and repelling themselves. It’s the same underlying data structure with a bit different axioms (conflicts allowed to be committed vs not; working tree is a commit vs isn’t).

Turns out these two differences combined with tracking change identity over multiple snapshots (git shas) allow for ergonomic workflows which were possible in git, just very cumbersome. The workflows that git makes easy jj also keeps easy. You can stop yelling at clouds and sleep soundly knowing that there is a tool to reach for when you need it and you’ll know when you need it.

lucianbr 2 days ago | parent | prev | next [-]

> you don't have a culture where

Yeah, and? Not everyone is in control of the culture of the organization they work in. I suspect most people are not. Is everyone on HN CEOs and CTOs?

hilariously 2 days ago | parent | next [-]

No, but there are a lot of them, and principal and staff engineers, and solo folks who would get to set the culture if they ever succeed.

A lot of people's taste making comes from reading the online discussions of the engineering literati so I think we need old folks yelling at clouds to keep us grounded.

nvader 2 days ago | parent | prev [-]

Temporarily embarrassed CEOs and CTOs

dwroberts 2 days ago | parent | prev [-]

I think the unspoken part is that the mess of commits is being produced by agents not people.

That’s why it’s always the same confusing hype when it’s discussed, because it’s AI/LLM hype effectively

surajrmal 2 days ago | parent [-]

I was in this situation long before llms came along. They may have exacerbated it a bit, but they are not the root cause.

stouset 2 days ago | parent | prev | next [-]

I don't get git. Every time it's posted people gush about how git enables some super complicated workflow that I can't wrap my head around. I have a simple edit/undo workflow in my editor that has served me well for decades so I guess I don't understand...

ehnto 2 days ago | parent | next [-]

There is a limit to how far one needs to abstract personally.

I don't layer my utensils for example, because a spoon is fit for purpose and reliable.

But if I needed to eat multiple different bowls at once maybe I would need to.

For my personal use case, git is fit for purpose and reliable, even for complex refactoring. I don't find myself in any circumstances where I think, gosh, if only I could have many layers of this going on at once.

sobjornstad 2 days ago | parent | next [-]

Even if you're working on one single thread of development, jj is easier and more flexible than git though. That it works better for super complicated workflows is just a bonus.

stouset a day ago | parent | prev [-]

jj reduces mental overhead by mapping far more cleanly and intuitively to the way people tend to work.

This is a little weird at first when you’ve been used to a decade and a half of contorting your mental model to fit git. But it genuinely is one of those tools that’s both easier and more powerful. The entire reason people are looking at these new workflows is because jj makes things so much easier and more straightforward that we can explore new workflows that remove or reduce the complexity of things that just weren’t even remotely plausible in git.

A huge one for me: successive PRs that roll out some thing to dev/staging/prod. You can do the work all at once, split it into three commits that progressively roll out, and make a PR for each. This doesn’t sound impressive until you have to fix something in the dev PR. In git, this would be a massive pain in the ass. In jj, it’s basically a no-op. You fix dev, and everything downstream is updated to include the fix automatically. It’s nearly zero effort.

Another is when you are working on a feature and in doing so need to add a capability to somewhere else and fix two bugs in other places. You could just do all of this in one PR, but now the whole thing has to b reviewed as a larger package. With jj, it’s trivial to pull out the three separate changes into three branches, continue your work on a merge of those three branches, and open PRs for each separate change. When two of them merge cleanly and another needs further changes, you just do it and there’s zero friction from the tool. Meanwhile just the thought of this in git gives me anxiety. It reduces my mental overhead, my effort, and gives overburdened coworkers bite-sized PRs that can be reviewed in seconds instead of a bigger one that needs time set aside. And I don’t ever end up in a situation where I need to stop working on the thing I am trying to do because my team hasn’t had the bandwidth to review and merge my PRs. I’ve been dozens of commits and several stacked branches ahead of what’s been merged and it doesn’t even slightly matter.

jychang 2 days ago | parent | prev | next [-]

If you think about it, git is really just a big undo/redo button and a big "merge 2 branches" button, plus some more fancy stuff on top of those primitives.

seba_dos1 2 days ago | parent [-]

"Merge 2 branches" is already far from being a primitive. A git repository is just a graph of snapshots of some files and directories that can be manipulated in various ways, and git itself is a bunch of tools to manipulate that graph, sometimes directly (plumbing) and sometimes in an opinionated way (porcelain). Merging is nothing but creating a node (commit) that has more than one parent (not necessarily two) combined with a pluggable tool that helps you reconcile the contents of these parents (which does not actually have to be used at all as the result does not have to be related to any of the parents).

(you may know that already, but maybe someone who reads this will find this helpful for forming a good mental model, as so many people lack one despite of working with git daily)

myst 2 days ago | parent | prev | next [-]

You haven’t helped anyone with this.

hansmayer 2 days ago | parent | prev [-]

Who posts about git? Its one of those tools that just work and don´t need hype.

uasi 2 days ago | parent | prev | next [-]

Even with that workflow jj can help a lot. Haven't you ever been annoyed by situations like, while working on a few features at once, having unrelated changes from different feature branches piling up in the stash? Or wanting to switch to another branch mid-rebase without losing your place? jj's working-copy-as-commit model and its first-class treatment of conflicts address those pain points.

RicDan 2 days ago | parent [-]

No? You work on something and finish it. At most I have 2-3 feature branches open. If none are in review, I have commits in them with current work. Maybe I use the stash 2-3 times a year when I am heavily experimenting with different implementations.

dwb 2 days ago | parent | prev | next [-]

I love Jujutsu because it makes my work simpler, whatever kind of branching/merging structure I use. It just has a better model for me than git.

anthrofract 2 days ago | parent | prev | next [-]

I stick to basic workflows most of the time, and it's still much better.

edu 2 days ago | parent [-]

I concur, seems that lately we’ve collectively forget about the KISS principle.

dwattttt 2 days ago | parent [-]

It's easy to forget that what's "simple" is a function of what tools we have. And our familiarity with them.

jnpnj 2 days ago | parent | prev | next [-]

Depending on people workflow/mindset we often face stacked branches, lots of fixup commits, and over the years new git commands and tricks emerged to deal with that but not in cohesive way I guess. JJ seems (I only tried it a short while long ago) to address just that.

quarkz14 2 days ago | parent | prev | next [-]

I didn't at first and let's be honest most of our workflow is within what you described, however in the era of AI assisted coding I found JJ more pragmatic. I can easily abandon or create new work without having to stash or commit etc. Another thing I really like about JJ it's undo, did I commit something and realised I forgot to add something? jj undo and undos the last operation. Not only my workflow is ergonomically more flexible because of JJ but also less forgiving without having to memorise a lot of git commands. And integrates with already git repos for smooth transition!

p_l 2 days ago | parent | prev | next [-]

The thing is, JJ makes mega merges easy... Which opens paths to simple but powerful workflows that match reality better. Having multiple converging changes, or even separated bits of history for $reasons becomes ready without rebar and serializing PRs.

And better conflict resolution means it often becomes viable to just have mega merge add next release

locknitpicker 2 days ago | parent | prev | next [-]

> I don't get JJ. Every time it's posted people gush about how JJ enables some super complicated workflow that I can't wrap my head around.

This. Things like stacks and mega-merges are huge red flags, and seeing enthusiastic people praising how a tool is more convenient to do things that raise huge red flags is perplexing.

Let's entertain the idea of mega-merges, and assume a tool fixes all tool-related issues. What's the plan to review the changes? Because what makes mega merges hard is not the conflicts but ensuring the change makes sense.

jamienicol 2 days ago | parent [-]

I use jj but not mega merges. But as I understand it you're not going to push the merge itself for review. It allows you to work locally on multiple branches at once. But when ready you push the individual branch, pre merge, for review.

What's the red flag about a stack?

socalgal2 2 days ago | parent | prev [-]

Sounds like a SVN user complaining about git

quicksnap 2 days ago | parent | prev | next [-]

Trying out jj is super low-risk--since it uses git as a backend, you can test it out and bail back to git without any drawbacks other than a detached head state.

And I hope you do. It is so much better than git in every way. It enables working with stacks and the aforementioned megamerges so easily, allowing me to continue working forward while smaller units of work are reviewed/merged.

When I first tried to use jj, I wasn't entirely committed and switched between jj and git. Finally I hit a breaking point being fed up with stacks/merges and tried jj _for real_.

I recommend to give it a serious try for a few solid days and use it exclusively to really understand it. You won't go back.

The jj Discord is a very helpful place. Thanks to everyone there. Great article Isaac!

Brajeshwar 2 days ago | parent | next [-]

I tried out with a tiny project. It is the muscle memory built up with Git that kicks in and wish that JJ does it. I went through all the raw mistakes and doing things the hard way with Git, that, my mind plays trick trying to use JJ with the Git mindset. For now, I have mapped all of my Git aliases to JJ equivalent. But I would like to learn it the right way and do it the JJ way. This is going to take time, I’ll go slow.

stouset 2 days ago | parent [-]

I really recommend just ripping off the band-aid and using jj "as intended". It took me only a day or two to adapt, and a week to feel like I am now a jj native. It's really a tiny cost to pay, and way less than the overhead of maintaining a bidirectional mental mapping between jj and git.

eru 2 days ago | parent | prev | next [-]

> Trying out jj is super low-risk--since it uses git as a backend, you can test it out and bail back to git without any drawbacks other than a detached head state.

Btw, the risk of trying out other modern version control systems is nearly as low: most of them are compatible with git and you can convert back and forth. That definitely includes mercurial etc.

locknitpicker 2 days ago | parent [-]

> That definitely includes mercurial etc.

People tried mercurial. They went back to git.

Shish2k 2 days ago | parent | next [-]

I tried Sapling (Facebook's fork of mercurial with more polished git-compatibility layers) and never looked back for any of my own projects.

I recently started a new job where the vanilla git CLI is the only git frontend installed on company servers, and the regressions in user-experience are painful :(

eru 2 days ago | parent | prev [-]

Some did, sure. I made a more limited claim: you can convert back and forth between mercurial and git.

locknitpicker a day ago | parent [-]

> Some did, sure.

Not some. I mean, even the few source code repository services that supported mercurial started dropping it.

See Bitbucket's announcement:

https://www.atlassian.com/blog/bitbucket/sunsetting-mercuria...

> According to a Stack Overflow Developer Survey, almost 90% of developers use Git, while Mercurial is the least popular version control system with only about 3% developer adoption. In fact, Mercurial usage on Bitbucket is steadily declining, and the percentage of new Bitbucket users choosing Mercurial has fallen to less than 1%.

onair4you 2 days ago | parent | prev | next [-]

I’ve been loving it for personal projects. But for work, some of our homebrew tooling relies heavily on hashes. So any operation that causes snapshotting to occur tends to lead to breakage that utterly confounds Claude. I tried giving it rules and instructions to make sure to sync git up to the correct commit for the current snapshot, but as soon as the signal for that is too week in the context it blows a gasket trying to figure out what has gone wrong.

e40 2 days ago | parent | prev [-]

As others have said before, I used Magit in emacs and thay already feels like a superpower compared to git alone.

nchmy 2 days ago | parent | prev | next [-]

Some fantastic tricks in this article. Will definitely improve my Megamerge game. Thanks!

Though, I'd be remiss not to mention that this (and any other) jj workflow would be much easier with jjui. It's the best TUI around, not just for jj

I proposed incorporating some of this article into it. https://github.com/idursun/jjui/discussions/644

VerTiGo_Etrex 2 days ago | parent | prev | next [-]

Makes me happy to see the influx of jj posts as of late. Great tool. Roughly this workflow is how I convinced a few friends to finally loosen their death grip on git and try something new.

bilekas 2 days ago | parent | prev | next [-]

I think I'm missing some major selling point of jj, to me it's just git with a different flow that might be more suitable for a rare few cases where heavy parallel work is happening, and even then git is fine if people know what they're doing, the idea of no staging areas doesn't appeal to me, mutable commits seems actively negative to me personally.

I understand if people are enjoying it great, but the amount of praise and 'this is revolutionary' comments I see makes me really feel I'm missing a beat.

jFriedensreich 2 days ago | parent | next [-]

You have to look at it from the workflow side not compare the tool on your current git workflow. Check out https://www.stacking.dev for a description of stacked commits, which is more the everyday workflow on jj than the octopus in this article.

codethief 2 days ago | parent [-]

> If using a tool doesn't speak to you, git is adding more support for stacking every day. The new --update-refs option lets you update a stack with fewer rebases; however, parts of the stacking process are still tedious (i.e. opening PRs on GitHub or any other provider).

This doesn't seem to be entirely up-to-date: http://github.github.com/gh-stack

dzaima 2 days ago | parent | prev | next [-]

Don't necessarily need heavy parallel work, or even anything parallel, to make use of jj; it's very nice for even just manipulating one local sequence of commits (splitting commits up, reordering them, moving files/hunks/lines between them or into/out of the working copy, without needing to checkout anything).

Won't get you much if you don't like to mutate commits in general, of course; at that point it's just a different committing workflow, which some may like and some dislike. (I for one am so extremely-happy with the history-rewriting capabilities that I've written some scripts for reinventing back a staging area as a commit, and am fine to struggle along with all the things I don't like about jj's auto-tracking)

As a fun note, git 2.54 released yesterday, adding `git history reword` and `git history split` in the style of jj (except less powerful because of git limitations) because a git dev discovered jj.

jychang 2 days ago | parent | prev [-]

Did you read the article?

> Basically, in the megamerge workflow you are rarely working directly off the tips of your branches. Instead, you create an octopus merge commit (hereafter referred to as “the megamerge”) as the child of every working branch you care about. This means bugfixes, feature branches, branches you’re waiting on PRs for, other peoples’ branches you need your code to work with, local environment setup branches, even private commits that may not be or belong in any branch. Everything you care about goes in the megamerge. It’s important to remember that you don’t push the megamerge, only the branches it composes.

> You are always working on the combined sum of all of your work. This means that if your working copy compiles and runs without issue, you know that your work will all interact without issue.

You don't even push the megamerge to the origin. Or perhaps you don't even need to push it. You can just... work off it.

bilekas 2 days ago | parent [-]

> You don't even push the megamerge to the origin.

But why would I do that with git anyway ? My local branch is what I'm working of, if I'm not ready to push, why would I ? I can as you say just work off it..

And when I'm ready to push, I prep my commit, because I'm expecting it to be immutable and pulled by others 'as-is'. Again, I must be missing something. I think the tool is just not for me, yet at least.

dwattttt 2 days ago | parent | next [-]

I've often found myself needing to work on two features at once, esp. where one has a dependency on the other. Maybe that branch is the real goal, and the other branch is an independent chunk of work that the feature needs.

Both get iterated on, because it's hard to know everything about a feature before it's done; maybe you find bugs that need fixing, or you realise you were missing something.

Rebasing the dependent branch onto the tip of the other branch gets you there, but as a workflow it's not pleasant, especially if you're not the only person working on the features... It's a recipe for conflicts, and worse that rebased branch conflicting with another person's view of it.

JonGretarB 2 days ago | parent | prev | next [-]

Another example is that there is this simple monorepo that holds both the latest _BlaJS_ frontend and the backend API.

You are working on stuff in the backend, but it sure would be nice to see it in the frontend so you jury rig something in the frontend to display your work as well as some console.log() commands. Then you forget to revert changes to the frontend before pushing the branch.

In jj you would start with these as separate branches. Then you work on a merge of these. Then you use the absorb command to auto-move the code you are working on to the correct branch or you squash the changed files to the branch. Then you can push the backend branch to server and PR it. Then you throw away the frontend branch or just leave it there so you can use it in a future feature.

A real case from my work. I had to work on an old Python project that used Poetry and some other stuff that was just not working correctly on my computer. I did not want to toucj the CD/CI pipeline by switching fully to uv. But I created a special uv branch that moved my local setup to uv. Then went back up the tree to main and created a feature branch from there. Merged them together and worked out from that branch moving all the real changes to the feature branch. Now whenever I enter that project I have this uv branch that I can merge in with all the feature branches to work on them.

pythonaut_16 2 days ago | parent | prev [-]

Imagine you have 3 branches: local-dev-tuneup, bugfix-a, feature-b

Remember in JJ you're always "in a commit", so the equivalent of the git working tree (i.e. unstaged changes in git) is just a new commit, often with no description set yet. (Because in JJ a commit also doesn't need a description/commit message immediately).

So in a mega-merge you can have a working tree that pulls from local-dev-tuneup, bugfix-a, and feature-b, and you can then squash or split changes out of it onto any of those source branches. Like you can avoid serializing those branches before you're ready to.

I've definitely faced the scenario in Git where I have a unmerged changes that I want to use while continuing work on a feature branch. I end up creating a PR for the branch of the first smaller features (e.g. local-dev-tuneup->master), then a second PR pointing at the first (feature-a -> local-dev-tuneup). It works but it's all a bit cumbersome, even more so if feature-a ends up needing to land before local-dev-tuneup. JJ has better tools for handling this.

Or potentially a team member has critical changes with a PR open and you want to start building on top of their changes now. Manageable in Git but you're locked in on a branch of their branch. Now add a second set of critical changes. Can be done in git but you'll be jumping through hoops to make it happen.

Of course you might say that all indicates a workflow/process problem, but my experience is this situations are common enough but not frequent.

(I haven't actually used megamerges myself yet but the article has me ready to try them out!)

b1temy 2 days ago | parent | prev | next [-]

I do not understand the appeal of the workflow of working on separate things in parallel, then splitting it off into branches/commits. imo, isn't it better to fully focus on one thing at a time, even if it is "simple"?

I imagine if I follow this workflow, I might accidentally split it off in a way that branch A is dependent on some code changes in branch B, and/or vice versa. Or I might accidentally split it off in a way that makes it uncompilable (or introduce a subtle bug) in one commit/branch because I accidentally forgot there was a dependency on some code that was split off somewhere else. Of course, the CI/CD pipeline/reviewers/self-testing can catch this, but this all seems to introduce a lot of extra work when I could have just been working on things one at a time.

I'm open to changing my mind, I'm sure there are lots of benefits to this approach, since it is popular. What am I missing here?

quicksnap 2 days ago | parent | next [-]

From practical experience from using jj daily and having (disposable) mega merges:

When I have discrete, separate units of work, but some may not merge soon (or ever), being able to use mega merges is so amazing.

For example, I have some branch that has an experimental mock-data-pipeline thingy. I have yet to devote the time to convince my colleagues to merge it. But I use it.

Meanwhile, I could be working on two distinct things that can merge separately, but I would like to use Thing A while also testing Thing B, but ALSO have my experimental things merged in.

Simply run `jj new A B C`. Now I have it all.

Because jj's conflict resolution is fundamentally better, and rebases are painless, this workflow is natural and simple to use as a tool

adrianmsmith 2 days ago | parent [-]

> Because jj's conflict resolution is fundamentally better

I don't know jj well so its merge algorithm may well be better in some aspects but it currently can't merge changes to a file in one branch with that file being renamed in another branch. Git can do that.

https://github.com/jj-vcs/jj/issues/47

duskdozer 2 days ago | parent | prev | next [-]

I don't think I really understand the way jujutsu is doing this, but if it's what I think, one example would be that you realize while working that some changeset is getting too big and makes sense to split it. So B would depend on A and be on top eventually, but you don't know the final form of B until you've finished with both. I've always just done this with rebasing and fixups, but I could see it being easier if you could skip that intermediate step.

usernametaken29 2 days ago | parent | prev | next [-]

Sometimes you want to work on something and as a prerequisite that needs X. Then you realise once X is in place you can actually build a number of useful things against X. And so forth. There’s no good way to merge sequentially, other then a multi merge

JonGretarB 2 days ago | parent | prev | next [-]

A real case from my work. I had to work on an old Python project that used Poetry and some other stuff that was just not working correctly on my computer. I did not want to touch the CD/CI pipeline by switching fully to uv.

But I created a special uv branch that moved my local setup to uv. Then went back up the tree to main and created a feature branch from there. Merged them together and worked out from that branch moving all the real changes to the feature branch.

Now whenever I enter that project I have this uv branch that I can merge in with all the feature branches to work on them.

faangguyindia 2 days ago | parent | prev | next [-]

>I do not understand the appeal of the workflow of working on separate things in parallel, then splitting it off into branches/commits. imo, isn't it better to fully focus on one thing at a time, even if it is "simple"?

because agents are slow.

I use SOTA model (latest opus/chatgpt) to first flesh out all the work. since a lot of agent harness use some black magic, i use this workflow

1. Collect all issues 2. Make a folder 3. Write each issue as a file with complete implementation plan to rectify the issue

After this, i change from SOTA to Mini model

Loop through each issue or run agents in parallel to implement 1 issue at a time.

I usually need to do 3 iteration runs to implement full functionality.

KPGv2 2 days ago | parent [-]

"because AI" isn't really a good answer since JJ was not created for AI, and most people who use JJ aren't just AI bots.

kalstone 2 days ago | parent | prev | next [-]

This can be especially useful in a monorepo where you may need to pull changes in from multiple other branches and projects and build on top of them

socalgal2 2 days ago | parent | prev | next [-]

I had a big feature I was working on. jj made it easy to split it into 21 small commits so I could give reviewers smaller things to review while I continued to work. It wasn't perfect and maybe git can do it all by itself but it's not my experience.

In other words, I effectively was working on one thing, but at a quicker easier pace.

conradludgate 2 days ago | parent [-]

I've been doing this in git for years. Interactive rebasing isn't that scary. At work we have a very big stacked PR culture on github using native git

tinodb 17 hours ago | parent | next [-]

But in general you are one of the few that does. Many devs do find git rebases scary. Having done it in both I can say with JJ it is much much simpler (especially with jjui).

rstuart4133 2 days ago | parent | prev [-]

> I've been doing this in git for years.

You've missed a crucial detail.

You've both been doing it, but only one of you was using a tool that needed rebases to pull it off.

jhhh 2 days ago | parent | prev | next [-]

It does seem to introduce a lot of complexity for its own sake. This kind of workflow only survives on the absorb command and like you said it doesn't really cover all the interplay of changes when separated. It's a more independent version of stacked diffs, with worse conceptual complexity.

baq 2 days ago | parent | prev | next [-]

> I do not understand the appeal of the workflow of working on separate things in parallel, then splitting it off into branches/commits.

Your repo is small and/or your CI is fast. You’ll understand in a big repo or when CI has to run overnight to get you results.

amonks 2 days ago | parent | prev | next [-]

I’ve found megamerge really helpful in cases where I’m working on a change that touches multiple subsystems. As an example, imagine a feature where a backend change supports a web change and a mobile change. I want all three changes in place locally for testing and development, but if I put them in the same PR, it becomes too hard to review—maybe mobile people don’t want to vouch for the web changes.

You’re right that I have to make sure that the backend changes don’t depend on the mobile changes, but I might have to be mindful of this anyway if the backend needs to stay compatible with old mobile app versions. Megamerge doesn’t seem to make it any harder.

BeetleB 2 days ago | parent | prev | next [-]

As a jujutsu user, I don't disagree. I can see the appeal of doing a megamerge, but routinely working on the megamerged version and then moving the commits to the appropriate branch would be the exception, not the norm.

I gather one scenario is: You do a megamerge and run all your tests to make sure new stuff in one branch isn't breaking new stuff in another branch. If it does fail, you do your debug and make your fix and then squash the fix to the appropriate branch.

baq 2 days ago | parent | prev | next [-]

If your CI pipeline takes hours and it has good reasons to you start to do things like this.

juped 2 days ago | parent | prev [-]

I wouldn't do it this exact way either but the benefit is "having any local throwaway integration branch" vs. having none at all. You don't need to do it this exact way to have one.

sukit 2 days ago | parent | prev | next [-]

Been trying to get into jj lately, but I rely a lot on VS Code's git gutter to review changes as I code. Doesn't look like jj has an equivalent in VS Code. Anyone got tool recommendations?

paradox460 2 days ago | parent | next [-]

There are a number of jj plugins for vsc. VisualJJ and Jujutsu Kaizen are probably the two most popular

https://www.visualjj.com/

https://github.com/keanemind/jjk

KPGv2 2 days ago | parent [-]

> jjk

what's next, "oh! my gitess"? "chainsvn man"?

FiloSottile 2 days ago | parent | prev | next [-]

I just use the VS Code git integration with the jj colocated git repo. HEAD is @- and the changes in @ are considered working copy changes. It works for all I was using the VS Code integration for.

nchmy 2 days ago | parent [-]

Same experience here

maleldil 2 days ago | parent | prev | next [-]

You should be able to use the normal git gutter as long as your repository is colocated.

joshka 2 days ago | parent | prev | next [-]

jjk or jjview

I have a PR up for jjk that does the full change as a review changes, and there's another user's PR that allows diffs over arbitrary ranges (i.e. when working out whether the commits that make up a PR are good as a whole rather than individually)

altano 2 days ago | parent | prev | next [-]

visualjj, it’s fantastic

2 days ago | parent | prev [-]
[deleted]
the_data_nerd 2 days ago | parent | prev | next [-]

You are not actually working in parallel. You are making the cost of stopping one thing near zero. In git, pausing A for B costs a rebase. In jj, you edit B, the stack reflows, you keep going. That is the whole thing. Context switches get cheap so you take them.

ksymph 2 days ago | parent | prev | next [-]

Semi off-topic, but does anyone know of good resources for jj that don't assume git knowledge? Steve's and others are high quality, but often things are explained in terms of git equivalents or describe workflows that I struggle to fully understand the purpose of, as someone who knows only the barest basics of git necessary to work on personal projects.

If none exist, I think there's a great opportunity there, for anyone with the knowledge and motivation to make some absolute beginner guides. Already jj is infinitely more user-friendly, and as the tool matures, it isn't far fetched to think a new generation of programmers could go straight to jj without knowing their way around git first.

incognito124 2 days ago | parent | next [-]

There's https://jj-for-everyone.github.io/

ksymph 2 days ago | parent [-]

> This is a tutorial for the Jujutsu version control system. It requires no previous experience with Git or any other version control system.

> At the time of writing, most Jujutsu tutorials are targeted at experienced Git users, teaching them how to transfer their existing Git skills over to Jujutsu. This tutorial is my attempt to fill the void of beginner learning material for Jujutsu.

Exactly what I was looking for, thank you!

quicksnap 2 days ago | parent | prev | next [-]

I'm not immediately aware. There's a certain amount of git-ness embedded in it with it being a DAG, having commits, and being compatible with git remotes. And, since the industry still runs on git, most people will need to learn it somewhat, anyway.

dbt00 2 days ago | parent | prev [-]

Honestly, until JJ is 1.0, I wouldn't recommend it for beginners. There's significant changes happening to the interface still.

maleldil 2 days ago | parent [-]

I've been using it in relatively the same way for a while now. The only meaningful changes were native support for `tug` and `absorb`, neither of which significantly changed my workflow.

dzaima 2 days ago | parent [-]

eh, there have been a good amount of breaking changes. `-d`/`--destination` → `-o`/`--onto` (the former isn't yet deprecated though); deprecated `--allow-new` on push (or, forcibly making it the default for `--bookmark`); deprecated `jj bookmark track foo@bar` (and `jj bookmark track foo` having a really-weird system (I personally just call it broken, even though the behavior is intentional) of sometimes tracking the bookmark on all remotes; really I'd call jj's entire system of bookmark tracking/pulling/pushing quite incomplete outside of the trivial cases); various changed revset functions over time that break configs; and a really-annoying thing of `jj git fetch` sometimes abandoning ascendants of `@` leaving you in a confusing state (if not one with conflicts), with the solution being a future `jj git sync`.

It's certainly very usable despite all that, and the changes are simple enough to adapt to, but it's a pretty new thing.

bombcar 2 days ago | parent [-]

I think for a real neophyte jj will be fine especially when used with the git backend.

Someone who "knows enough to be dangerous" may be better served by sticking with the git happy-path.

Of course, if working with others you should use what they do until you're confident that you can switch without impacting them.

chaychoong 2 days ago | parent | prev | next [-]

Great writeup! I've been using `jj parallelize` [1] a lot (and wrote about it here [2]) to fan out a sequence of commits to set up a megamerge, but your stack alias sounds super useful to create them on the fly, rather than at the very end of a work stream. Thanks for the tips!

[1] https://docs.jj-vcs.dev/latest/cli-reference/#jj-parallelize [2] https://blog.chay.dev/parallelized-commits

chrishill89 2 days ago | parent | prev | next [-]

Sometimes I have several pull requests to review and none of them have any meaningful overlap (e.g. they touch code in different places, no apparent risk of overlap). So I've started making integration branches to test all of them in one go. But then I sometimes find things to improve upon. Then I might make a few commits on top of that. And then later I have to manually move them to the correct branch. I might also remove them from the integration branch, but git-rebase(1) is likely to just drop them as already-applied.

My mind was a little blown when I read about the megamerge strategy in Steve Klabnik's tutorial.[1]

Yes, Jujutsu's approach of autorebasing changes is very nice. Now all I have to do is to try it myself.

† 1: https://steveklabnik.github.io/jujutsu-tutorial/advanced/sim...

eddd-ddde 2 days ago | parent [-]

With JJ I sometimes make a 'jj new a b c' to work on top of multiple changes. Then as I tweak things 'jj absorb' to automatically patch the right changes.

Insanely easy and effective.

anthrofract 2 days ago | parent | prev | next [-]

I enjoyed this article a lot, gave me some new ideas for my Jujutsu TUI, Majjit:

https://github.com/anthrofract/majjit

nvahalik 2 days ago | parent | prev | next [-]

Great article, Isaac!

If anyone is JJ-curious, I also can't recommend the Discord[1] enough. The community is very helpful and welcoming.

[1]: https://discord.com/invite/dkmfj3aGQN

juped 2 days ago | parent | prev | next [-]

It's interesting to see the strange workflows that come from jujutsu users, as someone who works on git workflows.

There's some counterproductive stuff in there from my perspective but at its core you're keeping up a throwaway integration branch, which is helpful practice if you'll ever care about an integration. It's annoying with git because the interface for updating your throwaway integration branch is very clunky and easy to get wrong.

qsera 2 days ago | parent | prev | next [-]

>The absorb command will do a lot of this for you by identifying which downstream mutable commit each line or hunk of your current commit belong in and automatically squashing them down for you. This feels like magic every time I use it (and not the evil black box black magic kind of magic where nothing can be understood), and it’s one of the core pieces of Jujutsu’s functionality that make the megamerge workflow so seamless.

IUUC This is already implemented for git as an extension. https://github.com/tummychow/git-absorb

I think this is such a basic thing that should be part of any DVCS implementation.

mhw 37 minutes ago | parent | next [-]

I've worked with git using the mega-merge approach, and one thing I found is that git-absorb won't merge commits into anything that precedes a merge. It works fine for absorbing changes into earlier commits on a feature branch, but not from the WIP branch back into the multiple feature branches that are the parents of the mega-merge. jj handles this with no problems.

From this comment on the git-absorb issue tracker I wouldn't expect it to be fixed soon either: https://github.com/tummychow/git-absorb/issues/134#issuecomm...

thierrydamiba 2 days ago | parent | prev [-]

Something really magical about “Distributed Version Control System” sharing an acronym with “Disney Vacation Club Services”.

vaylian 2 days ago | parent | prev | next [-]

One of the golden rules of git is: Don't rewrite public history (for example by rebasing and force-pushing already published commits). The article hints at immutable and mutable commits (https://isaaccorbrey.com/notes/jujutsu-megamerges-for-fun-an...) but I am unsure about how fundamental this protection is. I don't want to ruin my co-worker's day by accidentally rewriting public history.

rstuart4133 2 days ago | parent | next [-]

Rewriting immutable commits is only "fundermental" if it's enforced upstream. You can always break the rule locally.

That said, jj will warn you if you try to edit an immutable commits, and you can configure what it considers immutable.

taberiand 2 days ago | parent | prev | next [-]

Don't rewrite shared public history

It's ok to force-push a branch that only you have worked on (and even in the case of others working on the same branch it can be fine as long as you communicate with them)

vaylian a day ago | parent [-]

I agree. This is a valid exception.

jamienicol 2 days ago | parent | prev | next [-]

There's a configurable setting for which changes are marked as immutable. The default works perfectly for my workflow (pull-only from upstream, rewrite and push freely to my fork). other workflows may presumably need to tweak it

https://www.jj-vcs.dev/latest/config/#set-of-immutable-commi...

seba_dos1 2 days ago | parent | prev | next [-]

More like a custom which sometimes has good reasons to be broken than a golden rule. A branch in Git is nothing but a pointer to a commit, anything more than that is social agreement that can differ in various contexts.

vrnvu 2 days ago | parent | prev [-]

Jujutsu is immutable for public changes by default.

You can force changes with a ‘—ignore-inmutable’ flag.

LoganDark 2 days ago | parent | prev | next [-]

I saw Jujutsu on HN a few days ago and gave it a try. I picked a bunch of it up in just a couple hours and a couple days later I've completely switched to it for all my projects, it's not even close. Git is dead to me.

I just wish Jujutsu supported git tags rather than only supporting bookmarks as branches. And I also wish that Jujutsu supported preserving commit dates during rebases.

One of my absolute favorite things about Jujutsu is how easy it is to manipulate the commit graph remotely without having to manually checkout each commit first. I've been working on some pull requests to their built-in diff editor lately trying to improve the user experience enough that most conflicts will be fixable without having to use a text editor.

Also, the lack of a special staging area means you also never have to fucking stash your changes before you can do practically anything. Your changes always have a place, you can always go somewhere else and you can always come back.

notmywalrus 2 days ago | parent | next [-]

> git tags

There are commands for manipulating tags (jj tag set, jj tag delete), and recently [1] support for fetching / pushing

[1]: https://github.com/jj-vcs/jj/pull/9279

LoganDark 2 days ago | parent [-]

Oh? That's incredibly recent. Thank you for letting me know. As it turns out, I just built jj from source earlier today, so ironically I should already have tags. I'll give it a try.

icorbrey 2 days ago | parent | prev | next [-]

Re: commit dates, fundamentally those always change when rebasing because you're rewriting the commit object, but we don't touch the author date unless you explicitly reset it with metaedit

LoganDark a day ago | parent [-]

I'm not sure which date GitHub displays, but whenever I change something early in history, the entire repo loses every date.

jordwest 2 days ago | parent | prev [-]

Same here, picked it up a week ago and haven’t touched git again.

Probably my favourite thing that has really changed my workflow is being able to write empty commits in advance then just switch between them. It helps me remember what I’m doing and whats next whenever I get distracted or take a break.

rixtox 2 days ago | parent | prev | next [-]

I found octopus megamerge hard to collaborate - my colleagues don't use JJ so they may introduce changes that would cause conflitcts to my megamerge. When you have a conflict on a change that has more than 2 parents, the conflict resolution becomes unmanageable very quickly. No merge tool can handle more than 3-way merge, so you have to do that manually.

Eventually I settled on a tree-like megamerge that's more practical: merge 2 branches at a time and merge the merged branch with the next branch. This way I only need to handle 2-way conflicts at a time which is more manageable.

Also you have to be very careful to decide the order when you (and your colleagues) are going to land the branches, or if you expect any new features other people are working on that's going to conflict with your branches. When using megamerger workflow, most of the problems come from coordinating with other colleagues.

icorbrey 2 days ago | parent [-]

Fwiw I've not had this experience, I use megamerges in teams of 8+ devs without much issue

grim_io 2 days ago | parent | prev | next [-]

If this works like I think it does, it might be the missing piece I've been waiting for, for actually trying jj. Thanks!

icorbrey 2 days ago | parent [-]

Awesome! Tbh other than GitButler idk where I'd even start if I had to recreate this with vanilla Git

krupan 2 days ago | parent | prev | next [-]

I reluctantly stopped using mercurial 10 or so years ago, and reading this brings a little tear to my eye. Mercurial was just about where jj seems to be now. It had revsets. It had just gotten the concept of mutable and immutable commits. It had absorb. It had bookmarks. It never had an "index". The commands had human readable options like I see in this post. It could work with git repositories. Man I miss it.

I'm hesitant to pick jj up in case it ends up losing to git like mercurial did. But it's very tempting.

rstuart4133 2 days ago | parent | next [-]

According to the guy who wrote JJ, he copied all the ideas you mentioned from hg. That included a lot of ideas from hg's add ons. So the similarities are no accident. But then he added a twist - he didn't just delete the index, he dropped "hg commit" as well.

I can't see it going anywhere. It is in many ways "just" a different porcelain for git. The plumbing is the same. It's also safer to use: no JJ command can lose data another JJ command can't recover.

thunderbong 2 days ago | parent | prev [-]

It can't really lose to git, because underlying it is git

Guvante 2 days ago | parent | prev | next [-]

"Evil" merged are only evil if your tooling skips over merge commits as "unimportant" which is a common tactic to try and prune some of the crazy trees you get when hundreds of people are making merge commits into a repo which then creates its own commits for automation reasons...

jiggunjer 2 days ago | parent | prev | next [-]

Strange advice not to push the mega merge. It's what I call my release branch.

One thing I like is there's many ways to achieve the same result. E.g. author uses a fancy rebase to graft a new branch between trunk and merge point. I could do the same by: 1) rebase -s onto trunk, 2) merge new branch with mega merge, 3) squash old megamerge upwards into new merge. No cryptic revset needed.

uhhhd 2 days ago | parent | prev | next [-]

I love this stuff as a hobbyist, but professionally I can't help but think this is all obsolete in the age of agent-driven development. I wish jj was around a decade ago.

MeetingsBrowser 2 days ago | parent | next [-]

I disagree. Easily reviewing and combining multiple streams of parallel work is more valuable than ever.

riwsky 2 days ago | parent | next [-]

With jj worktrees, you can even have agents working on each of those sub-megamerge branches in parallel.

rndhouse 2 days ago | parent | prev | next [-]

I've been playing around with agent-native source annotation to specifically address the massively parallel work problem. Check it out here: https://github.com/draxl-org/draxl

uhhhd 2 days ago | parent | prev [-]

You don’t need jj for this anymore. The whole premise of optimizing human workflows around source control is becoming obsolete.

When LLMs are driving development, source control stops being an active cognitive concern and becomes a passive implementation detail. The unit of work is no longer “branches” or “commits,” it’s intent. You describe what you want, the model generates, refactors, and reconciles changes across parallel streams automatically.

Parallel workstreams used to require careful coordination: rebasing, merging, conflict resolution, mental bookkeeping of state. That overhead existed because humans were the bottleneck. Once an LLM is managing the codebase, it can reason over the entire state space continuously and resolve those conflicts as part of generation, not as a separate step.

In that world, tools like jj are optimizing a layer that’s already being abstracted away. It’s similar to how no one optimizes around assembly anymore. It still exists, it still matters at a lower level, but it’s no longer where productivity is gained.

qsera 2 days ago | parent | next [-]

> The unit of work is no longer “branches” or “commits,”

It better be, now and going forward for people who use LLMs..because they will need it when LLM messes up and have to figure out, manually, how to resolve.

You ll need all the help (not to mention luck) you need then..

skydhash 2 days ago | parent | prev | next [-]

A lot of words to say "LLMs are good for this, trust me bro!"

You're bashing the old way, but you do not provide any concrete evidence for any of your points.

> The unit of work is no longer “branches” or “commits,” it’s intent.

Insert <astronaut meme "always has been">.

Branching is always about "I want to try to implement this thing, but I also want to quickly go back to the main task/canonical version". Committing is about I want to store this version in time with a description of the changes I made since the last commit. So both are an expression and a record of intent.

> Parallel workstreams used to require careful coordination: rebasing, merging, conflict resolution, mental bookkeeping of state.

Your choice of words is making me believe that you have a poor understanding of version control and only see it as storage of code.

Commits are notes that annotates changes, when you want to share your work, you share the changes since the last version everyone knows about alongside the notes that (should) explain those changes. But just like you take time to organize and edit your working notes for a final piece, rebasing is how you edit commits to have a cleaner history. Merging is when you want to keep the history of two branches.

Conflict resolution is a nice signal that the intent of a section of code may differ (eg. one wants blue, the other wants red). Having no conflict is not a guarantee that the code works (one reduces the size of the container, while the other increase the flow of the pipe, both wanted to speed up filling the container). So you have to inspect the code and run test afterwards.

Discard the above if you just don't care about the code that you're writing.

uhhhd 17 hours ago | parent [-]

I think we’re talking past each other. My point isn’t that jj is bad. It’s that it’s solving problems that are rapidly becoming irrelevant.

Tools like git and jj exist to help humans manage state: branches, commits, rebases, conflicts, history curation. That whole model assumes a human is directly manipulating and reasoning about the codebase.

With LLMs in the loop, that assumption breaks. I don’t need to think in terms of branches or commits. I describe intent, and the model handles the mechanics of editing, reconciling, and producing a coherent result. Source control becomes an implementation detail of the toolchain, not something I actively operate.

jj is an improvement over git for humans, but that’s exactly why it feels like a local maximum. It refines a workflow that is already being abstracted away.

I’m not saying version control disappears. I’m saying it moves down a layer, the same way memory management or instruction scheduling did. When that happens, optimizing the human interface to it matters a lot less.

skydhash 16 hours ago | parent [-]

> Tools like git and jj exist to help humans manage state: branches, commits, rebases, conflicts, history curation. That whole model assumes a human is directly manipulating and reasoning about the codebase.

Think about the following first. You got a problem in the real world and if you can subdivide it into smaller problems, you will find that some are simple enough that a computer can take care of it and never be bored while doing it. And due to the last decades a lot of them have ready-made solutions. But you have to coordinate those solutions and write a program. And for these you need to write instructions into a text files.

But the real world is not static and you can't figure out the solution in one go, so you have to do iterative works on it. And unlike real world, the only cost of modifications is time. But you still want backups and the ability to restore version. So here come version control for the code of the software.

So you start thinking about all the possible workflow you could do with checkpoints you can return to in a few minutes, and it will look very close to something like git (or cvs). The one thing is that the computer is very removed from the problem that is driving all the changes and instead is at the other side. So it can magically correct issues and instead you have to step in.

> With LLMs in the loop, that assumption breaks. I don’t need to think in terms of branches or commits. I describe intent, and the model handles the mechanics of editing, reconciling, and producing a coherent result.

That would be great if that was possible now, but that looks like a synopsis for some SF novel. I can use git or jj today, but your version is lacking the several steps that would be making this a daily occurrence.

> memory management or instruction scheduling

You may think that they did, but that's until you have to deal with a memory leak or concurrent tasks. What we want version control for is the capability to snapshot state and restore to a known state and to share changes (instead of whole folder) when collaborating. How it's done does not really matter but git's conceptual model is very close to be ideal (at least for text files and line based statements). And its UX is versatile enough to be adaptable for all sort of workflow.

surajrmal 2 days ago | parent | prev [-]

There are a lot of assumptions baked into your assessment. We are not at the point where manual workflows are obsolete. Maybe it is for folks who work on web apps, but it's certainly not the case for many others. AI Agents are constantly making mistakes and need oversight. Things have gotten dramatically better, but not enough for me to trust it to not create a terrible mess.

nozzlegear 2 days ago | parent | prev | next [-]

I've found agents like Claude are absolute ass at fixing any halfway complex merge conflict. I won't trust them to do it.

rstuart4133 2 days ago | parent [-]

You trust Claude (or any AI) to do anything right? The odds are good - but never 100%.

That said, "jj new -A @", get Claude to do it's thing, "jj squash" is going to be pretty safe.

nozzlegear 2 days ago | parent [-]

No, I don't trust AI to do much of anything. I've written in other comments on HN that I mostly use it to write draft commit messages and pull requests that I review and rewrite myself, now that the honeymoon phase has ended. But when I was still attempting to get it to do more, I found Claude Code was really bad at trying to fix conflicted merges and rebases, always dropping the wrong parts of the code and leaving me with a broken codebase and a commit message history that didn't make sense for the changes inside.

JonGretarB 2 days ago | parent | prev | next [-]

Oh I would say that jj is exactly the kind of VCS needed for agentic workflows.

Anonymous branches. Easy to move things around. Always succeeding merges. Megamerges. Worktrees not bound to branches.

quicksnap 2 days ago | parent | prev | next [-]

I have been using Claude for 95% of the mechanical coding for months, and jj has proven to be more relevant than not for me. Because it is a better VCS tool than git, it allows to work with the firehose of commits much more seamlessly.

baq 2 days ago | parent | prev | next [-]

Actually it’s more relevant than ever since agents trivially parallelize work, but it still needs to be validated together. You can work on individual branches in worktrees and have the ‘megamerge’ in yet another.

chrishill89 2 days ago | parent | prev [-]

Let's say that this is obsolete for professional programming. Can't us hobbyists be left alone to our hobby by the LLM demoralization patrol?

CodeCompost 2 days ago | parent | prev | next [-]

I was skeptical at first but when I dragged and dropped a bookmark in `gg` then a light went on in my head. Also the fact that jujutsu does everything in "detached mode" locally means that you can't mess up your remote git repo (unless you force push all yolo from git itself, but you're never expected to do that).

taberiand 2 days ago | parent | prev | next [-]

How does the megamerge handle the case where two included branches overlap in changes and a new commit is made that applies to the overlap?

icorbrey 2 days ago | parent | next [-]

This is something you have to generally handle manually since absorb won't squash hunks with ambiguous targets, but I typically stack these branches and accept the dependency. I have had instances where this has backfired a little bit re: ordering but thankfully with JJ and the very patient little man in my computer named Codex it's easy to reorder them and end up with the same diff

nvahalik 2 days ago | parent | prev [-]

The mega merge wouldn't handle that based on the way the article shows. You COULD have a revset that includes stacked changes, though. That does work and is what I currently do.

nchmy 2 days ago | parent [-]

Could you please elaborate on how you do this?

nvahalik 2 days ago | parent [-]

If you have a dependency tree like this:

       / A \
      -- B - Megamerge 
       \ C /
There is nothing stopping you from doing this:

       / A - D \
      -- B ----- - Megamerge 
       \ C - E /
(Edit, or even this:)

       / A - D \
      -- B ----- - Megamerge 
       \ C ----/
          \ E /
Where E stacks on C and D stacks atop A. In the case above, A-E are revsets of either 1 or more commits. JJ doesn't care if they are or not. You'd generally bookmark the revset on the final "commit" as the pointer.

           / features/add-widgets
          /  / features/add-widget-integration
       / A - D \
      -- B ----- - Megamerge 
       \ C - E /
          \   \ feature/add-new-page
           \ feature/rework-navigation
In the example above, let's say you rework the navigation. You could have it exist alongside the navigation rework, but changes are you don't want to do the work twice. You just say "hey, this depends on the nav rework" and so it's there inside of the repo.

The thing is there is another way to do this where you end up with 4 different parents in a megamerge and your nav rework touches the megamerge and your new page is yet another revset is just a fork off of it. But yeah... JJ gives you a lot of flexibility in this manner.

nchmy a day ago | parent [-]

Thanks!

polskibus 2 days ago | parent | prev | next [-]

Can this technique help with fixing a bug on master then having to merge it easily to older release-branches , without resorting to cherry-picking (and losing all history)?

domysee 2 days ago | parent | prev | next [-]

It sounds like the same workflow that GitButlers UI has. Can anyone with more knowledge than me confirm or deny that?

icorbrey a day ago | parent | next [-]

If you inspect a GitButler repo with JJ you can see that it's topologically identical actually! https://bsky.app/profile/isaaccorbrey.com/post/3m33wrahz4222

PinkFluffyLlama 2 days ago | parent | prev [-]

JJ's mega-merge was inspired by GitButler, so yes! It is very similar.

dbt00 2 days ago | parent | prev | next [-]

this is great stuff. I've been ad hoc building a version of this workflow, and it is quite fantastic.

I'm still not as smooth at figuring out conflicts on mega-rebase.

forrestthewoods 2 days ago | parent | prev | next [-]

Great post. Thanks for sharing.

icorbrey 2 days ago | parent [-]

Thanks!

incognito124 2 days ago | parent | prev | next [-]

Finally

icorbrey 2 days ago | parent [-]

Look man life gets busy and I'm horrible at accepting "good enough" lol

schpet 2 days ago | parent [-]

love to see it, been looking forward to this.

zeristor 2 days ago | parent | prev | next [-]

Setting up 6 AI worker agents and as ever they end up committing over each other, really slows down my parallel work process using git.

Next up once my Sunday morning token allowance is to look at using git.

techpulselab 2 days ago | parent | prev | next [-]

[dead]

huflungdung 2 days ago | parent | prev [-]

[dead]