DEV Community

Cover image for Let the Agent Write the Code. Write the Commit Message Yourself
Gabriel Anhaia
Gabriel Anhaia

Posted on AI-assisted

Let the Agent Write the Code. Write the Commit Message Yourself


Six months from now, someone on your team runs git blame on the session config. They land on sameSite: "lax" and open the commit. The message reads: Change session cookie sameSite to lax. The diff under it says the same thing in code. Strict looks safer than Lax, so they change it back. The next morning, nobody can sign in.

The message was accurate. An agent wrote it from the diff, and it said nothing the diff didn't already say. The one fact that would have stopped the revert, why Lax was chosen over Strict and over the other fixes on the table, never made it into the history.

Let the agent write the code. Write the commit message yourself, or at least the paragraph that says why.

The diff is already in the commit

Run git show on any commit. Git's own manual says what you get: "For commits it shows the log message and textual diff." Open the commit in git show or any history viewer and the diff is right there under the message.

A message generated from the diff can only translate the diff into English. That's what generators are built to do. VS Code's smart actions page offers a sparkle icon that writes commit messages "based on your code changes." The result can be tidy, imperative, with a short first line. It's also redundant, because the reader who opens that commit is already looking at the code it describes.

That's not a knock on the generators. A summary line is useful in git log --oneline, and agents write good ones. The problem is everything below the summary line.

What Git asks a commit message to carry

Git's project rules for contributors, SubmittingPatches, are blunt about the purpose: "The goal of your log message is to convey the why behind your change to help future developers." The body, it says, should:

  1. explain the problem the change tries to solve, "what is wrong with the current code without the change"
  2. justify the way the change solves it, "why the result with the change is better"
  3. list "alternate solutions considered but discarded, if any"
  4. record "the resolution of design or viability concerns raised by the community during the review, if any, ensuring the historical record explains why the chosen approach was accepted over alternatives"

Read items 3 and 4 again. Alternatives discarded. Concerns raised in review. Why this approach was accepted. None of that is in the diff, and most of it happens after the agent has finished typing.

The Linux kernel's patch guidance opens the same section with three words: "Describe your problem." Git's commit manual adds the shape: a short first line of "no more than 50 characters," a blank line, then "a more thorough description."

Same diff, two messages, six months later

Here is the whole change from the opening, a cookie option on the session middleware:

 cookie: {
   httpOnly: true,
   secure: true,
-  sameSite: "strict",
+  sameSite: "lax",
 },
Enter fullscreen mode Exit fullscreen mode

The message an agent drafts from that diff looks like this:

Change session cookie sameSite to lax

Update the session cookie configuration to use
SameSite=Lax instead of SameSite=Strict.
Enter fullscreen mode Exit fullscreen mode

Now the message you can write after reviewing the work. Say the bug was "sign-in with the identity provider always fails," and the agent's first attempt was to skip the OAuth state check on the callback. You rejected that turn and kept the second one:

auth: send session cookie on OAuth callback

Sign-in through the identity provider fails every
time. The provider sends the browser back to
/auth/callback with a cross-site GET. A Strict
cookie is not sent on cross-site requests, so the
callback finds no session and the state check fails.

Lax sends the cookie on cross-site top-level GET
navigations only. Cross-site POST, PUT and DELETE
still go out without it, and every state-changing
route in this app is a POST.

Rejected in review: skipping the state check on the
callback (the first attempt), and a second Strict
cookie just for the login round-trip.

Do not switch this back to strict without moving
the OAuth state out of the session cookie.
Enter fullscreen mode Exit fullscreen mode

The cookie behaviour in that message is straight from MDN's Set-Cookie reference: Strict sends the cookie "only for requests originating from the same site that set the cookie," while Lax also sends it on cross-site top-level navigations that use a safe method, which "excludes POST, PUT, and DELETE." The subject follows the "area: " prefix and imperative mood that SubmittingPatches asks for, and the problem is in the present tense, as it also asks.

Six months later, the person holding the revert runs this:

git blame -L 1,8 src/session.js
git log -L 1,8:src/session.js
git log --grep=OAuth
Enter fullscreen mode Exit fullscreen mode

git blame prints, for each line, the abbreviated commit name, the author and date, and the line number. git log -L traces the evolution of that line range, commit by commit, with the patch. --grep limits the log "to ones with a log message that matches" the pattern.

With the agent's message, blame and log -L both end at the same sentence: the value changed from strict to lax. True, and already visible in the patch. --grep=OAuth finds nothing at all, because the message never mentions the problem. With yours, the reader learns the failure, the constraint, the two fixes that lost, and an explicit warning. That warning is the line that stops the revert.

Why the agent can't write that paragraph

The agent saw the code, the error, and its own turns. It did not see why you rejected turn one, unless you typed the reason into its terminal. It does not know that every state-changing route being a POST is a rule your team relies on. It was not in the thread where someone asked about a second cookie. Some of the why can end up in the transcript. The part that decided the outcome usually came from you, after you read the work.

SubmittingPatches makes one more point worth keeping: "you often discover your own bugs yourself, while writing the log message to summarize the thought behind it." Writing the why is a last review pass. Hand the message to the agent and you skip that pass too.

You don't have to write the whole thing by hand. Keep the split simple: the agent drafts the subject line and the summary, and you write the problem, the reason and what you rejected. A commit template keeps you honest. commit.template names a file to start every message from:

git config --global commit.template ~/.gitmessage
Enter fullscreen mode Exit fullscreen mode
# Problem (present tense, without this change):
#
# Why this fix over the alternatives:
#
# Rejected in review:
Enter fullscreen mode Exit fullscreen mode

When you commit in an editor, Git's default cleanup mode strips "commentary," so the # prompt lines disappear and only your answers stay. If you exit without editing, the commit is aborted. Commits made with -m skip the template entirely, which is one more reason not to let a tool commit with a one-liner.

Where you know the why: in review, before the commit

I build Hermes IDE, so weigh this section with that in mind. Hermes runs Claude Code, Codex and other agents in their own terminals, each task on its own hermes/<name> branch and worktree. Every agent turn is saved, so you can diff or restore any single turn.

Press ⌘G (Ctrl+Shift+G on Windows and Linux) and the Review Desk shows the changes by turn or by file, with risk flags. A line comment goes back to the agent that wrote that line. When you're done, Land commits, opens a pull request or merges locally in one step, into the branch the task started from, and it can be undone.

The Hermes Review Desk in By turn view for a Claude Code task in orders-api, listing two turns, turn 1's diff of src/db.ts and a commit message drafted from the turns
The Review Desk (⌘G) in By turn view: two turns (T1: 3 files +69 −1, T2: 1 file +1 −0), turn 1's diff of src/db.ts adding a refunded status, the changed files, and a commit message drafted from the turns.

The Review Desk also shows a commit message drafted from the turns, as in the screenshot above, and that draft is the what. It is a fine starting point and it has the same limit as every generated message: it was built from the changes. The moment you finish reading turn by turn, you know which turn you rejected and why the one you kept is better. That is when to write the paragraph, before you press Land. If you'd rather start from your own template, the task branch is plain git: run git commit in its worktree and your commit.template applies.

Hermes is free, source-available under BSL 1.1, and runs on macOS, Windows and Linux. Version 2.3.4 shipped on October 15, 2026. It's not affiliated with Nous Research, Anthropic, OpenAI or any agent vendor.

So, where do you draw the line? Does your agent write the whole message, or do you keep the why for yourself? Tell me in the comments.


If this was useful

The session cookie in this post sits right where most small teams get bitten: auth and the deploy that ships it. Ship It covers that stretch between localhost and production for a small team, from hosting and payments to auth, CI/CD and monitoring. If you want to try the review-then-commit flow, download Hermes IDE or star it on GitHub.

Ship It — the pragmatic startup tech stack

Top comments (0)