Navigate
HomeStart here
MusingsResearch & long-form
BuildingProjects & learnings
WorkProfessional practice
RunningTraining & races
AboutValues & identity
Life & PlacesCulture, food, travel, cities
Notes & ArchiveJournals, essays, portfolio
← Back to Building
PATTERNMar 2026

When Auto-Commits Obscure History

I had an auto-commit hook that committed after every Claude Code session. 122 commits later, git log was useless — every message said "auto-sync session data."

gitversion-controlworkflowhygiene

I set up a hook in `.claude/hooks/` that ran on SessionEnd. Every time I closed a Claude Code session, it would commit whatever had changed. The idea was safety — never lose work, always have a restore point. It worked exactly as designed. Within a few weeks I had 122 commits, and every single one said "auto-sync session data."

The problem became obvious when I needed to find when the Strava migration happened. `git log --oneline` was 122 lines of identical messages. I couldn’t bisect a bug because every commit was a grab bag of unrelated changes. A commit might contain a CSS fix, a new API route, and a whitespace edit in a config file. The safety net had destroyed the history it was supposed to protect.

I squashed all 122 commits into 5 meaningful ones: the site-wide spacing fix (51 files, CSS shorthand root cause), the Strava-to-Supabase migration (296 activities), the Oura/Strava sync path fix (3 bugs), the FTI Research Tools cross-variable analysis, and the initial site setup. Each one describes what actually changed and why. `git log` is useful again. I can bisect. I can read the history like a changelog instead of a heartbeat monitor.

The rule I landed on: auto-commit is a safety net, not a history. Keep the hook — it runs locally only and never pushes. But periodically, sit down and squash the auto-commits into meaningful history that describes decisions, not sessions. The commit message should answer "what changed" and "why," not "Claude Code was open."

This raised a bigger question I haven’t answered yet: what’s the version control strategy? Should I use feature branches for risky work? Preview deploys before merging to main? Tagged releases for milestones? Right now it’s just main-branch-everything, which works fine for a solo project but won’t scale if I start collaborating. That decision is pinned for a future session. For now, the auto-commit hook stays, the periodic squash is the discipline, and `git log` tells a story again.

# Before: 122 commits of noise
# git log --oneline
# a3f2d1c auto-sync session data
# b4e5f6a auto-sync session data
# c7d8e9f auto-sync session data
# ... (119 more)

# After: 5 meaningful commits
# git log --oneline
# 9824289 Fix site-wide spacing (51 files, CSS shorthand root cause)
# a1b2c3d Migrate Strava data to Supabase (296 activities)
# d4e5f6g Fix Oura/Strava sync paths (3 bugs: path, sort, static import)
# h7i8j9k Add FTI Research Tools cross-variable analysis
# l0m1n2o Initial site setup and IO dashboard

# The rule:
# Auto-commit = safety net (local only, never push)
# Meaningful commit = human decision (what changed, why)
# Periodically squash auto-commits into meaningful history