LmCast :: Stay tuned in

Defeating Git Rigour Fatigue with Jujutsu

Recorded: May 24, 2026, 8:58 p.m.

Original Summarized

defeating git rigour fatigue with jujutsu | ikesau.coi  <esaudefeating git rigour fatigue with jujutsucomputersThis post assumes a basic level of familiarity with the
jujutsu version control system. If you haven't used jujutsu, you'll still get the gist of the idea, but I
recommend reading
Steve's Jujutsu tutorial
after.When developing a large feature, writing Good Commits is hard.And by Good Commits, I mean something like:define types
add DB functions
server CRUD
client API
client UIThis allows reviewers to step through your pull request in small bites, with
each set of changes scoped to a single aspect of the feature.So, naturally, here's what I do instead:define types
add DB functions
WIP test code
server CRUD
client API and UI
fix DB function
fix UI bug
refactor CRUD
fix another UI bugLatter commits overwrite work that was done in earlier commits and the story
breaks.⚖️Jujutsu makes it easier to hop around commits and iterate quickly on
compartmentalized changesets, but it's still effortful and I get averse.🤖jj absorb helps somewhat, as does
jj squash -i, but they both have their downsides:absorb assigns the changes based on whichever
previous commit most recently touched those files, which sometimes doesn't
actually correspond to which commit should own these particular
changes.squash can get you stuck in merge conflict hell
if your boundaries aren't extremely clean.So here's a solution to this problem of "git rigour fatigue" that I've come
up with.For this example, let's represent commits visually. Imagine
red represents
changes to the type definitions,
blue to the UI
and so on:Mayhem. Our first commit is a mix of
red and
blue. We touch
red in multiple
places!To fix this, let's create our ideal commit history first, using
jj new -B messy-first -m 'red'Then we can do the rest. (I switch to
jj new -A red -m 'blue' at this point)Then we squash all the commits with actual changes in them into one with
jj squash --from messy-first..messy-last --into messy-firstThen we use
jj squash -i --from --into red
and pick out the red changes, putting them into the red box:And so on:Eventually everything's in the right place and the "everything commit" is
empty.For large features, I find this workflow far easier than having to maintain
strict git rigour for the lifecycle of the feature's development. It's
easier to make improvised commits with temp debugging state in them and tidy
it all up in one sweep at the end.preemptions:I don't have a good name for this technique. "Doing Commits Like A Big
Pile Of Laundry", perhaps?This is different from (and, imo, superior to)
jj split:With split, if I miss a hunk that should have
been in red,
I have to split again and squash.This technique more easily allows sorting the easiest hunks at the
beginning without worrying about how it will effect the commit
sequencing.This reason why doing it all at the end is (often) better than using
jj squash -i as you go is because the final state
of the everything commit is guaranteed to not have any conflicts. Creating
a new "fix red and green" commit and interactively squashing that into
your red and green commits might break your blue commit if it happens to
touch one of the affected files.A downside to this technique is that there's no guarantee that every
commit will compile, which might be a dealbreaker.⚖️
Some people prefer this, as it helps
git bisect work better. Debuggability versus
reviewer convenience is the tradeoff, I guess.🤖
Especially in a world of LLM agents, that will gladly fix bugs for you
that span multiple boundaries in 30 seconds.

The author addresses the difficulty of maintaining strict commit rigor when developing large features, noting that achieving good commit hygiene—such as defining types, adding database functions, server CRUD operations, client APIs, and user interfaces—is challenging. This lack of compartmentalization often results in subsequent commits overwriting earlier work and breaking the overall development story, a phenomenon termed git rigor fatigue. While version control systems like Jujutsu facilitate iteration on compartmentalized changesets, the process still demands significant effort, presenting the problem of managing this complexity. Existing tools like jj absorb and jj squash -i offer partial relief but introduce their own complications; jj absorb assigns changes based on the most recent file modification, which may not align with logical commit boundaries, and jj squash risks entering merge conflict scenarios if boundaries are poorly defined.

To mitigate git rigor fatigue, the author proposes a specific workflow designed to manage these compartmentalized changes efficiently. The core solution involves visualizing commits using color coding to represent distinct areas of change, such as red for type definitions and blue for user interface elements. The proposed methodology suggests creating an ideal commit history first, perhaps using jj new -B messy-first, to establish a baseline structure. From there, the process involves making the necessary changes and then consolidating the history by squashing the changes into the appropriate color-coded boundaries. For instance, one might perform initial messy commits and then iteratively use commands to isolate and squash changes pertaining to specific areas, ensuring that the final consolidated commit reflects only the intended changes for that segment, effectively eliminating the "everything commit" with no extraneous content.

This technique is contrasted with methods like jj split, which requires splitting and squashing for every missed modification, potentially complicating the sequencing. The author argues that performing the consolidation at the end is superior because it guarantees that the final state of a commit will not contain conflicts, unlike interactive squashing mid-process, which might inadvertently compromise unrelated changes. A recognized drawback of this approach is the lack of an absolute guarantee that every resulting commit will pass compilation, which could be a significant barrier depending on the project requirements.

The trade-off inherent in this technique involves balancing debuggability for reviewers against strict compile-time guarantees. The author suggests that this trade-off is favorable, especially in environments where rapid debugging is essential, such as when interacting with systems involving LLM agents that can quickly resolve multi-boundary bugs. This workflow prioritizes reviewer convenience and the ability to iterate quickly over absolute compile-time integrity for the sake of managing the development lifecycle of large features.