EzAI
Back to Blog
Tutorial Mar 8, 2026 8 min read

Build an AI Git Commit Message Generator

E

EzAI Team

Build an AI Git Commit Message Generator

Writing good commit messages is one of those things every developer agrees matters, yet most of us skip when we're deep in flow. The result: a git log full of "fix stuff", "wip", and "asdfasdf". We're going to fix that in about 50 lines of Python using the EzAI API to generate commit messages that actually describe what changed.

The tool reads your staged diff, sends it to Claude (or any model available through EzAI), and returns a properly formatted Conventional Commit message. You review it, hit enter, and you're done. No more agonizing over wording at 2 AM.

How It Works

AI commit message generator flow diagram — git diff to EzAI API to formatted commit message

The pipeline: capture staged changes → analyze with AI → generate a structured commit message

The flow is straightforward. When you run the tool, it:

  1. Runs git diff --staged to capture exactly what you're about to commit
  2. Sends that diff to EzAI's API with a prompt tuned for Conventional Commits
  3. Parses the response and presents it for your approval
  4. Runs git commit -m with the generated message if you accept

The key insight: we send the raw diff, not a summary. The AI sees exactly which lines changed, which functions were modified, and what files were touched. This produces dramatically better messages than any template or heuristic could.

Prerequisites

You'll need Python 3.8+ and an EzAI API key. If you don't have one yet, sign up — you get 15 free credits, which is enough for hundreds of commit messages since we'll use a fast, cheap model.

bash
pip install anthropic

The Complete Script

Here's the full tool. Save it as aicommit.py anywhere on your PATH:

python
#!/usr/bin/env python3
import subprocess, sys, os
import anthropic

EZAI_KEY = os.environ.get("ANTHROPIC_API_KEY", "sk-your-key")
EZAI_URL = os.environ.get("ANTHROPIC_BASE_URL", "https://ezaiapi.com")
MODEL = os.environ.get("AICOMMIT_MODEL", "claude-sonnet-4-5")

SYSTEM_PROMPT = """You are a git commit message generator. Given a git diff, write a
single commit message following the Conventional Commits spec.

Rules:
- Format: type(scope): description
- Types: feat, fix, refactor, docs, style, test, chore, perf, ci
- Scope: the primary module or file area affected (optional)
- Description: imperative mood, lowercase, no period, max 72 chars
- If the change is complex, add a blank line then bullet points
- Never explain what Conventional Commits is — just write the message
- Output ONLY the commit message, nothing else"""

def get_staged_diff():
    result = subprocess.run(
        ["git", "diff", "--staged"],
        capture_output=True, text=True
    )
    return result.stdout.strip()

def generate_message(diff: str) -> str:
    client = anthropic.Anthropic(
        api_key=EZAI_KEY,
        base_url=EZAI_URL
    )
    resp = client.messages.create(
        model=MODEL,
        max_tokens=300,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": diff}]
    )
    return resp.content[0].text.strip()

def main():
    diff = get_staged_diff()
    if not diff:
        print("No staged changes. Run 'git add' first.")
        sys.exit(1)

    # Truncate massive diffs to stay under token limits
    if len(diff) > 12000:
        diff = diff[:12000] + "\n... (diff truncated)"

    print("Generating commit message...")
    msg = generate_message(diff)

    print(f"\n\033[1;32m{msg}\033[0m\n")
    choice = input("[a]ccept / [e]dit / [r]egenerate / [q]uit: ").lower()

    if choice == "a":
        subprocess.run(["git", "commit", "-m", msg])
    elif choice == "e":
        edited = input("Edit message: ") or msg
        subprocess.run(["git", "commit", "-m", edited])
    elif choice == "r":
        main()
    else:
        print("Aborted.")

if __name__ == "__main__":
    main()

That's 52 lines including blank lines. The cost per commit message is roughly $0.001–0.003 depending on diff size — you could generate 5,000 messages for a dollar.

Making It a Git Alias

The real power comes from integrating this into your git workflow. Add it as a git alias so you can run git ai from any repo:

bash
# Make it executable
chmod +x aicommit.py
sudo cp aicommit.py /usr/local/bin/aicommit

# Add the git alias
git config --global alias.ai '!aicommit'

# Now use it like this:
git add -p                # Stage your changes
git ai                   # Generate + commit

Switching Models

One advantage of routing through EzAI: you can swap models without changing code. The AICOMMIT_MODEL environment variable controls which model handles your diffs.

For commit messages, you don't need the most powerful model. Sonnet handles this perfectly. But if you're working on a complex refactor and want the deepest analysis, you can switch to Opus for that session:

bash
# Default: fast and cheap
git ai

# For complex refactors: use Opus
AICOMMIT_MODEL=claude-opus-4 git ai

# Try GPT-4.1 for comparison
AICOMMIT_MODEL=gpt-4.1 git ai

# Use Gemini for free-tier commits
AICOMMIT_MODEL=gemini-2.0-flash git ai

All of these models are available through EzAI's unified endpoint. Same API key, same base URL, same code — just a different model string. Check the full list on the pricing page.

Tuning the Prompt

The system prompt above produces solid Conventional Commits by default. But you can customize it for your team's conventions. Here are some variations worth trying:

  • Jira ticket extraction: Add "If the diff touches files in a feature branch named PROJ-XXX, include the ticket number in the scope"
  • Emoji prefixes: Some teams use gitmoji — add "Prefix with a relevant emoji (🐛 for fix, ✨ for feat, etc.)"
  • Multi-line bodies: For detailed changelogs, add "Always include a body with bullet points explaining why, not just what"
  • Breaking changes: Add "If the diff removes or renames public API functions, add BREAKING CHANGE: footer"

The prompt is just a string — modify it to match whatever your team's CONTRIBUTING.md says about commit format.

Handling Large Diffs

The script truncates diffs over 12,000 characters, which covers most commits. But for massive refactors that touch 50+ files, you might want a smarter approach. Here's a diff summarizer that feeds the AI a compressed version:

python
def compress_diff(diff: str, max_chars: int = 12000) -> str:
    if len(diff) <= max_chars:
        return diff

    # Use git's stat summary + first N chars of actual diff
    stat = subprocess.run(
        ["git", "diff", "--staged", "--stat"],
        capture_output=True, text=True
    ).stdout

    header = f"DIFF STAT:\n{stat}\n\nFIRST {max_chars} CHARS OF DIFF:\n"
    remaining = max_chars - len(header)
    return header + diff[:remaining]

This gives the AI the full file-level summary (--stat) plus as much of the actual diff as fits. It's enough context to write an accurate message even for large changesets.

CI Integration: Auto-Generated Changelogs

Once your team is generating consistent commit messages, you unlock automatic changelogs. Since every message follows Conventional Commits, tools like conventional-changelog can parse them into release notes without manual effort.

The pipeline becomes: write code → git ai → push → CI generates changelog → release. The AI-generated messages are the glue that makes this entire chain work automatically.

Cost Breakdown

Running this through EzAI keeps costs negligible. Here's a realistic estimate for a team of 5 developers, each making ~10 commits per day:

  • Average diff size: ~2,000 tokens input
  • Average response: ~50 tokens output
  • Model: Claude Sonnet via EzAI (~60% cheaper than direct)
  • Daily cost: 50 commits × ~$0.002 = $0.10/day
  • Monthly cost: ~$2–3 for the entire team

That's less than a single cup of coffee for a month of professionally formatted commit history. Check EzAI's current pricing for exact per-token rates — Sonnet through EzAI is significantly cheaper than going directly through Anthropic.

What's Next

You've got a working AI commit message generator in 50 lines of Python. From here you can extend it: add --amend support for fixing the last commit, pipe output to pbcopy for clipboard integration, or build a PR description generator that uses similar logic on branch diffs.

The code, the prompt, and the EzAI integration are all intentionally simple. That's the point — the less friction between "I staged my changes" and "I committed with a good message," the more likely you are to actually do it. Good commit hygiene shouldn't require willpower.

Grab your API key from the EzAI dashboard and try it on your next commit. Your future self — and anyone who has to read your git log — will thank you.


Related Posts