How I Use AI to Write Better Git Commit Messages

Let me guess: your git log looks like a crime scene.

fix stuff, WIP, asdf, final FINAL v2, ok this time for real — I’ve seen it all. I’ve written it all. And if you’re honest with yourself, so have you.

Here’s the thing nobody talks about: bad commit messages aren’t just an aesthetic problem. They’re a tax. Every time someone has to git bisect through your garbage history, or stare at a 6-month-old commit trying to understand why you deleted that function — that’s time and cognitive load that could’ve been saved with 30 extra seconds of care.

The good news? AI has made those 30 seconds nearly effortless. Here’s the exact system I use.

Why Commit Messages Still Matter (Even With AI Code Tools)

Every AI code assistant on the market helps you write code faster. Not one of them helps you think about why you wrote it.

That’s what commit messages are for.

A good commit message answers:

  • What changed? (the diff tells you this, but in code-speak)
  • Why did it change? (context that the diff cannot tell you)
  • What’s the impact? (breaking change? New feature? Bug fix?)

When a commit message answers all three, future-you (or your teammate at 11pm on a Friday) can navigate the codebase like it has a GPS. When it doesn’t, you’re spelunking with a flashlight held between your teeth.

The real reason everyone still writes bad commit messages is friction. You’re in flow, you’ve solved the problem, and stopping to write a thoughtful summary feels like hitting a speed bump. AI removes that friction. Let’s get into how.

The Anatomy of a Great Commit Message: Conventional Commits

Before we talk tools, we need a standard. I use — and recommend — the Conventional Commits specification (conventionalcommits.org). It’s widely adopted, tooling-friendly, and takes about 5 minutes to learn.

The format:

<type>(<scope>): <short description>

[optional body]

[optional footer]

Types you’ll use most:

TypeWhen to use
`feat`New feature
`fix`Bug fix
`docs`Documentation only
`refactor`Code change that isn’t a fix or feature
`chore`Tooling, deps, build config
`test`Adding or updating tests
`perf`Performance improvement
`ci`CI/CD changes

Real examples:

feat(auth): add OAuth2 login with Google provider

fix(cart): prevent duplicate items when rapid-clicking add button

refactor(api): extract rate-limiting middleware to shared module

chore(deps): bump lodash from 4.17.20 to 4.17.21

Clean, scannable, tool-parseable. Your changelog practically writes itself.

Method 1: GitHub Copilot Chat — Generate from Your Diff Directly

If you’re already using GitHub Copilot ([get it here]#), this is the fastest path from diff to commit message.

Step 1: Stage your changes normally.

git add -p   # or git add <files>

Step 2: Get your diff.

git diff --staged

Step 3: In VS Code, open Copilot Chat and paste this prompt:

📋 Copilot Chat Prompt Template

Here is a git diff of my staged changes:

<paste diff here>

Write a conventional commit message for these changes following this format:
<type>(<scope>): <short imperative description under 72 chars>

Then add a 2-3 sentence body explaining WHY these changes were made (not what — the diff already shows that).

If there's a breaking change, add a footer: BREAKING CHANGE: <description>

Use these types: feat, fix, docs, refactor, chore, test, perf, ci

Copilot will produce something like:

fix(payment): handle declined card response from Stripe webhook

Stripe's webhook was returning a 402 with a nested error object that
wasn't being caught by the existing error handler. This caused silent
failures where declined payments showed as "pending" in the dashboard.

Added explicit handling for payment_intent.payment_failed events.

Compare that to what you probably would’ve typed: fix payment bug.

The quality delta is enormous, and it took you maybe 20 seconds.

Method 2: ChatGPT / Claude Prompts for Summarizing Staged Changes

Don’t have Copilot? No problem. ChatGPT Plus ([link]#) or Claude work great for this too, and you can get even more specific with your prompts.

The key is giving the model enough context. Here’s my go-to prompt that I keep saved as a snippet in Raycast:

📋 ChatGPT / Claude Prompt Template (Copy-Paste Ready)

You are a senior developer reviewing a git diff. Generate a conventional commit message.

Rules:
1. First line: <type>(<scope>): <description> — imperative mood, under 72 chars
2. Blank line after first line
3. Body: 2-4 sentences explaining the REASON for the change (not what changed)
4. If it's a breaking change: add "BREAKING CHANGE:" footer
5. Types: feat, fix, docs, refactor, chore, test, perf, ci

Diff:
<paste your git diff --staged output here>

Output only the commit message. No explanation, no markdown code blocks.

The “output only the commit message” instruction is important — without it, ChatGPT tends to explain its reasoning, which you then have to strip out.

Pro tip: Save this as a Raycast snippet with the keyword ,commit. Then you can type ,commit, paste your diff, and submit in under 10 seconds.

Method 3: CLI Tools — commitizen, aicommits, and Others

If you want to automate even further, several CLI tools do this at the command line without any copy-paste.

commitizen

npm install -g commitizen cz-conventional-changelog
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

Then replace git commit with git cz. It walks you through a guided prompt:

? Select the type of change: (Use arrow keys)
❯ feat:     A new feature
  fix:      A bug fix
  docs:     Documentation only changes
  ...

Not AI-powered, but it enforces the standard and takes the guesswork out of structure. I recommend this as a starting point for teams that are new to conventional commits.

aicommits

npm install -g aicommits
aicommits config set OPENAI_KEY=<your-key>

Then just run aicommits after staging your files. It calls the OpenAI API, reads your diff, and generates a commit message automatically. You confirm before it commits.

It’s solid. The main downside is that it costs API credits per commit — small amounts, but worth knowing.

Other options worth knowing

  • git-commit-ai — Similar to aicommits, slightly different prompt style
  • cz-git — commitizen adapter with AI generation built in
  • Copilot CLI (gh copilot suggest) — If you’re in the GitHub ecosystem already

For most developers, I’d recommend starting with commitizen to build the habit, then layering in AI generation once you’re comfortable with the format.

My Personal Workflow: The 30-Second Commit Ritual

Here’s exactly what I do, every time:

1. Stage deliberately.

git add -p

I never git add . anymore. Reviewing hunks forces me to think about what I’m actually committing, which makes the subsequent message easier to write.

2. Get the diff.

git diff --staged | pbcopy   # macOS
git diff --staged | xclip    # Linux

Pipes the diff straight to clipboard. No manual selection.

3. Trigger my Raycast snippet.

I type ,commit in ChatGPT or Claude, which expands my prompt template. I paste the diff into the placeholder and hit send.

4. Copy the output, commit.

git commit -m "fix(auth): prevent session expiry during active requests

Token refresh logic was only triggered on 401 responses, missing the
case where tokens expire mid-request. Added proactive refresh 60s
before expiry using a background interval check."

Total time: 25-35 seconds. Including the time to think about whether the generated message is accurate (always review it — the model occasionally misreads intent).

Common Pitfalls to Avoid

1. Accepting AI output without reading it.

The model doesn’t know your codebase’s intent. It reads code, not decisions. If you changed a caching strategy for a reason that isn’t obvious in the diff, you need to either add context in the prompt or edit the output.

2. Using AI to dress up one-line diffs.

If your diff is - return false / + return true, a 4-sentence commit body is overkill. Match the message length to the change complexity.

3. Skipping the why in your prompt.

The best results come from prompts that include context beyond the diff:

Context: This fixes a bug reported in issue #412 where users on Safari 
couldn't complete checkout. Root cause was a missing Temporal API polyfill.

Diff: <diff here>

That context ends up in the message body, and it’s genuinely useful 6 months later.

4. Generating commit messages for massive diffs.

If your diff is 800 lines, break the commit up first. Atomic commits + AI = great history. Monolithic commits + AI = a confused model writing a confused message.

Before & After: Real Examples

Here’s what the difference looks like in practice.

Example 1 — Bug Fix

Commit Message
**Before**`fix login bug`
**After**`fix(auth): redirect to intended URL after SSO login`
**With body**Added 2-sentence explanation that OAuth callback was discarding the `next` query param, causing all SSO logins to land on `/dashboard` regardless of original destination.

Example 2 — New Feature

Commit Message
**Before**`add export thing`
**After**`feat(reports): add CSV export for billing summary view`
**With body**Clarifies that export is scoped to admin roles only, and is behind the `billing-export` feature flag pending QA sign-off.

Example 3 — Refactor

Commit Message
**Before**`cleanup`
**After**`refactor(db): replace raw queries with Prisma ORM in user module`
**With body**Notes that this is a non-functional change and all tests pass, but migration guide is needed before deploying to staging.

The after versions aren’t just prettier — they’re load-bearing. They tell the story of the codebase.

Steal This: The Master Prompt Template

Keep this somewhere accessible (Raycast, Alfred, a notes app — anywhere you can paste it fast):

You are a senior developer reviewing a git diff. Generate a conventional commit message.

Rules:
1. First line: <type>(<scope>): <description> — imperative mood, under 72 chars
2. Blank line after first line  
3. Body: 2-4 sentences explaining WHY the change was made (not what)
4. If breaking change: add "BREAKING CHANGE: <description>" footer
5. Types: feat, fix, docs, refactor, chore, test, perf, ci
6. Output only the commit message — no explanation, no markdown fences

Optional context (add if relevant):
- Related issue: #<number>
- Known limitations or follow-up needed: <notes>
- Breaking change details: <description>

Diff:
<PASTE YOUR git diff --staged OUTPUT HERE>

This template works with ChatGPT, Claude, Copilot Chat, or any capable LLM. Copy it, save it, use it on every commit.

Your future self — and your teammates — will notice the difference within a week.

Quick Reference: Tools & When to Use Them

ToolBest forCost
GitHub Copilot ChatVS Code users already on Copilot~$10/mo
ChatGPT PlusBest output quality, flexible prompts~$20/mo
ClaudeLong diffs, nuanced contextFree tier available
commitizenTeams new to conventional commitsFree
aicommitsFully automated CLI flowPay-per-use API
RaycastSnippet management, macOSFree tier available

Better commit messages won’t make you a better developer overnight. But they’ll make you a more considerate one — and your codebase will carry that forward long after you’ve moved on.

\ This post contains affiliate links. If you sign up for GitHub Copilot or ChatGPT Plus through links in this post, I may earn a small commission at no extra cost to you. I only recommend tools I actually use.*

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top