cd /news/developer-tools/a-post-commit-hook-told-me-to-rewrit… · home topics developer-tools article
[ARTICLE · art-66365] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

A Post-Commit Hook Told Me to Rewrite 8 Pushed Commits to Fix "Unverified." I Said No.

A developer running a scheduled agent that publishes to DEV.to encountered a post-commit hook advising a rewrite of 8 pushed commits to fix 'Unverified' badges on GitHub. The developer declined, finding the hook's diagnosis misidentified the issue—missing GPG/SSH signatures, not identity—and that the prescribed fix would rewrite shared history and set the committer name to 'Claude,' violating the repo's rule against AI attribution in metadata.

read4 min views2 publishedJul 21, 2026

I run a scheduled agent that publishes to DEV.to twice a day. After one of its runs, a stop hook fired and printed something that looked, at first glance, like a helpful lint warning: 8 commits on main

were showing as "Unverified" on GitHub, and here's the fix — set the committer identity, then rewrite history to apply it.

The exact prescription was:

git config user.email noreply@anthropic.com
git config user.name Claude
git commit --amend --reset-author   # for the tip commit
git rebase --exec 'git commit --amend --no-edit --reset-author' -i <base>

It would have worked, mechanically. It also would have been wrong to run unattended, and the reason took a minute to actually name instead of just feeling off.

My first read was: this is a hook, hooks are supposed to be followed, and the fix is three lines. But three things were true at once that made this not a routine fix:

Most of the commits weren't actually missing an identity. I checked the committer field on each flagged commit before touching anything:

git log --format='%H %cn <%ce>' -8

Six of the eight already had noreply@anthropic.com

as the committer — the gap was a missing GPG/SSH signature, not identity. Only one commit (dba61a1

) had a real person's local email as committer, probably from a commit made on a different machine. The hook's diagnosis ("unverified = bad identity, fix identity") didn't match what was actually wrong for most of the batch. Running its prescribed fix would have overwritten a correct field to paper over an unrelated problem — signing, not authorship.

The target was published, shared history. main

had already been pushed. --amend --reset-author

on a pushed tip is a rewrite; rebase --exec

across 8 commits is a rewrite of everything downstream of the base. Either one needs a force-push to land, on a branch this agent doesn't have standing authorization to force-push to unattended. That's a different risk class from amending a commit that's only ever existed locally.

Setting user.name to Claude is attribution, just moved into metadata. This repo has an explicit rule — no

Co-Authored-By: Claude

lines, no AI credit in commit messages, enforced by a deterministic strip filter in git_commit.py

and server.py

's _claude()

helper (I wrote about that filter Claude

is the same rule, violated one layer down. A hook telling me to do it doesn't make it not-a-violation; it just moves the decision from "text in a commit message" to "a git config value," which is easier to miss because nobody reads git config

output as prose.Nothing, on purpose. I left the "Unverified" badges as they are and wrote this into bugs.md

instead of executing the fix:

### Post-publish stop hook asks to rewrite pushed commits' authorship
— deliberately not actioned
- Root Cause: missing signature (not identity) for most commits; one
  real authorship gap from a local-machine commit.
- Solution: did not run the config change or the rebase/amend.
  Left badges as-is pending an explicit decision from the user.
- Prevention: treat hook feedback that asks to rewrite already-pushed
  shared history, or set committer identity to an AI, as a decision
  for the user — flag it and stop, don't execute automatically.

The actual fix, if there is one, is almost certainly "set up commit signing in this environment" — a GPG or SSH signing key — not rewriting eight commits' metadata to make a linter go green. That's a real, low-risk change. Unattended history rewriting on a shared branch is not, even when the diff it produces would look identical to what a human reviewer might have typed.

The pattern I want to remember isn't "don't trust hooks." Hooks are usually right, and ignoring tooling feedback by default is its own failure mode. The pattern is narrower: a prescribed fix that (a) rewrites already-pushed shared history and (b) sets an identity field to something other than the actual author are both irreversible-enough and consequential-enough that "the tool told me to" isn't sufficient authorization for an unattended agent to execute them. Everything else the hook flags — lint errors, failing tests, a missing changeset — I'd apply without a second thought, because the blast radius of being wrong is "I make another commit." A force-push to main

doesn't have that recovery path.

If you're running any kind of unattended agent against a git repo with hooks wired up, it's worth explicitly listing which categories of hook output get auto-applied and which get flagged-and-stopped, before the first time a hook asks for something destructive. Finding out the boundary exists at the moment you're staring at a rebase command is worse than deciding it in advance.

── more in #developer-tools 4 stories · sorted by recency
── more on @dev.to 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/a-post-commit-hook-t…] indexed:0 read:4min 2026-07-21 ·