Commit Messages from Four Models, Judged by the Reviewer
Four Models, One Diff, One Tired Reviewer
The scene is familiar: a branch with one refactor, one small bug fix, and a stray rename, forty minutes before standup, with the commit message cursor blinking. I pasted the same git diff into four models and asked each one for a subject line and a body, then read all four drafts the way a reviewer reads a patch, top to bottom, out of patience and looking for something to object to.
Routing the four calls took one key and one base URL, https://api.fluxorelay.com, which is the part I appreciate most when I am already inside Claude Code or Codex and do not want to leave the editor to babysit provider dashboards. Gemini CLI and anything built on an OpenAI SDK point at the same endpoint, and the model list stays honest: Claude Sonnet 5.5, GPT-6.1 Sol, DeepSeek V4 Flash, and Gemini 3.8 Flash were the four I pulled for this run, while the shelf also carries Claude Opus 5.5, Kimi K3, Qwen3.8 Max, Grok 4.7, MiMo V2.6 Pro, and GLM-5.3 when a task wants a different temperament.
Cost stayed a non-event. Fluxo bills per real token including cache reads and writes, with no monthly fee, so running one diff through four models costs exactly what those four completions cost and nothing else. For a ritual you repeat fifty times a month, that predictability matters more than any single model.
The verdict came fast, and none of it was about model quality. All four produced grammatical English, and none produced a message I would merge untouched. The failures clustered into a handful of habits, and every habit has a fix you can write into your prompt once and then forget.
- All four opened with an imperative verb and then hid the module name.
- Three of the four invented a summary section that repeated the diff.
- Two dropped the ticket trailer and replaced it with vague reference prose.
- Only one draft mentioned the behavior change visible to external callers.
- None of the drafts flagged the breaking change in the response shape.
Subjects That Rename the Ticket Instead of the Change
The most common mistake across all four drafts was a subject line that could sit on top of a dozen unrelated commits. Phrases like 'Update user module' and 'Improve error handling' force a reviewer to open the diff just to learn what the commit did, which defeats the entire point of writing the subject in the first place.
Models drift toward these phrases because a diff is noisy and a subject is short, so they reach for the safest abstraction available, and that abstraction is almost always the ticket title. The fix is mechanical: ask for the module, the behavior, and the direction of change inside fifty characters, then reject any draft that puts a task identifier or a folder name there instead.
Subjects are also where model formatting habits leak out. One draft wrapped its subject in decorative punctuation, and another padded it with a scope tag that matched no convention anywhere in the repository. State the convention explicitly in the prompt, paste one good example from the last five commits, and the imitative part of the model works in your favor instead of against it.
- Subjects that rename the ticket rarely survive a reviewer's first quick skim.
- A subject line under fifty characters should still name the touched behavior.
- Task identifiers belong in trailers where release tooling can parse them.
- Vague verbs like improve and update force the reviewer to open the diff.
- Concrete subjects let a reader scan the branch log and skip safely.
Bodies That Retell the Diff Instead of Explaining the Choice
A commit body has one job: to carry the reasoning that the patch cannot show. Why this approach over the obvious one, what changed for callers, and what deliberately did not change. Every model I tried instead restated the file list in prose, which adds exactly zero information a reviewer cannot already see in the patch itself.
The second shared habit is hedging. Drafts said the change seems to improve latency, may reduce allocations, possibly fixes the race. A commit message is an assertion made by the person who wrote the code, and hedging reads like the author was not there. Ask for declarative sentences, forbid modal hedging verbs in the prompt, and the tone tightens immediately.
Length and formatting went wrong too. One draft produced a body with nested bullets and decorative separators that survive neither an oneline log scan nor most release notes tooling. Keep bodies to short paragraphs, allow at most one flat list, and tell the model that the body is read in a terminal with limited width and zero patience.
- A body that restates the file list gives the reviewer no new information.
- Declarative sentences read far better than hedged claims inside a commit log.
- Every body paragraph should answer one question the reviewer will actually ask.
- Timing and benchmark numbers belong in the message only when they explain a tradeoff.
- Hedging words like possibly and seems weaken an otherwise correct explanation.
Breaking Changes and Trailers Dropped From the Log
The third mistake is the risky part going missing. When the diff removes a field or changes a response shape, all four drafts either buried that fact in the middle of a paragraph or left it out entirely. Reviewers scan the end of a message first, so risk has to be findable at a glance, and a breaking change that hides is a breaking change that ships.
The fourth is trailers. Signed-off-by lines, ticket keys, and reference identifiers are parsed by release tooling, and a model that rewrites them into friendly prose breaks the pipeline hours later on a Friday. Keep the original trailers verbatim, instruct the model to append rather than reformat, and verify them before you push instead of trusting the draft.
Multi-commit branches exposed another pattern: the same model wrote near-identical messages for three different commits because the diffs were siblings. Ask for one message per diff, include the neighboring commit subjects in the prompt for context, and require each subject to distinguish its own change from its neighbors.
- Breaking changes deserve their own sentence near the end of the body.
- Trailers must stay machine-readable because release tooling parses their structure directly.
- Rollback hints save the on-call engineer a lot of guessing at night.
- Merge commit subjects should say what came in rather than summarize generically.
- Repeated subjects across commits make a branch log impossible to scan quickly.
The Reviewer Checklist That Fixed All Four Drafts
I turned the review into a short checklist and put it at the top of my commit-message prompt. The checklist describes the artifact rather than any particular model, which is why it works unchanged across the shelf. Claude Haiku 4.5 gets a compact version for quick commits, GPT-6 Astra gets the full version plus the diff, and both land much closer on the first attempt than they did before.
- Name the module and the behavior change in the first fifty characters.
- Explain the reasoning behind the chosen approach in one short paragraph.
- Separate caller-visible changes from internal refactors so reviewers can scan faster.
- Put breaking changes and rollback notes where reviewers will find them first.
- Preserve existing trailers and add new ones without reformatting their structure.
- Delete hedging words, marketing adjectives, and any sentence that adds no information.
The loop around that checklist is cheap. Generate two or three drafts, pick the strongest, feed the checklist violations back as a short correction pass, and regenerate once. Because billing is per real token including cache reads and writes, the correction pass usually costs less than the first draft, since the diff stays in cache instead of being paid for again.
That workflow is what keeps Fluxo inside my editor rather than beside it. One key, one base URL, the same OpenAI-compatible calls whether I am scripting from the terminal or wiring a custom tool, and a bill that reflects real usage with no monthly fee. People you invite who end up paying also earn you a referral share of what they spend, which is a pleasant surprise rather than a reason to spam anyone.
If you would like to try this on tonight's branch, creating a Fluxo account takes about a minute. And if the checklist does not match your team's conventions, leave a note on the contact page after signing in.