AI-Era Git: Keep Working History Messy, Keep Main Clean

Some Day in May 2026: More “Mystery Commits” Again

I caught myself chuckling at Git history today.

fix lint
fix type
retry
temporary workaround
revert
another fix

This is what I see all the time when I let AI agents write code.

Humans already produce messy work-in-progress commits, but AI cuts them even finer.

It runs trial-and-error at high speed.

For AI, “save often in small steps” is rational, so this behavior is, in a way, natural.

Git History Gets Messier Than It Used To

Humans used to commit in fairly chunked units.

In the AI era, commit count itself tends to balloon.

And AI doesn’t share the human sense of aesthetics:

These thoughts don’t bother AI.

The result is that working branches get pretty chaotic.

Personally, I don’t think this is a bad thing.

Messy Working History Is Actually Natural

Working-state history is inherently muddy to begin with.

Even humans end up with things like:

fix
fix2
real fix
typo
WIP

That’s because it’s a “thought log.”

History that looks clean from the very first commit is closer to a “cosmetic record” written after the fact.

So a somewhat messy working branch is fine on its own.

The problem is when that messy history flows into main.

That’s Why Squash Merge Makes a Lot of Sense

The approach that feels most reasonable to me right now is:

Squash Merge.

That is:

This pairs really well with the AI era.

Your working branch might look like:

fix lint
retry
temporary fix
revert
another fix

But on main, only this remains:

Add user list API

Now history reads in “feature units.”

So Far, That Was the “Merging to Main” Side

What Squash Merge solves is:

“Don’t let AI’s mass commits land in main.”

That’s a main-side problem.

But Git operations have another, separate problem.

Namely, keeping your working branch in sync with the latest main.

This isn’t about reducing commit count; it’s about keeping your branch from drifting. Squash doesn’t address it.

Rebase for Branch Sync, and Why It’s Scary

The traditional way to sync with the latest main is rebase.

git fetch origin
git rebase origin/main

History becomes linear.

Technically beautiful.

In practice, though, rebase is widely disliked.

Conflict hell, force-push accidents, breaking shared branches — these still happen routinely.

Note that rebase is just rearrangement, so commits like fix lint / retry / revert themselves remain after a rebase.

Commit reduction is Squash’s job; branch sync is rebase’s job. Different roles.

But If Squash Cleans Things Up, Do We Even Need Rebase?

Writing this out, I started to wonder.

Rebase does have real upsides: linear history, no merge-commit noise, easier-to-read PRs.

But once you’re using Squash Merge, the main side collapses to one commit anyway, so the shape of the working branch never persists in the first place.

What’s left of rebase’s value is “readability during PR review,” which is fairly cosmetic.

Meanwhile the downsides — required force-push, repeated conflict resolution, AI losing context mid-rebase — add up quietly.

For just keeping a personal branch in sync with main,

git pull

is often enough.

“Letting AI handle rebase on a personal branch” is fine.

But it’s not essential when you’re already using Squash Merge — that’s my current take.

AI-Era Git: “Build Messy, Leave Clean”

People used to say:

“Make clean commits.”

In the AI era, a different workflow feels more realistic:

The star is Squash Merge. Rebase is just an option. Framing it that way reduces the number of things you need to think about.

The philosophy of Git itself doesn’t change.

One note: the pull-vs-rebase debate is theological, so this is just my personal preference. No counterarguments accepted (lol).