Auto generating git commit messages with AI using Bash and Go

Feb 14, 2025

Ever found yourself staring at git commit -m wondering how to describe your changes? Let's build a script that uses OpenAI's GPT to generate meaningful commit messages from your git diffs. We'll explore two implementations: one in Bash and an improved version in Go.

High quality git commit messages are a great way to improve your workflow. They are important because allow you (or other developers working on your code) to quickly see what changes were made and why.

It can be quite time consuming to write a good commit message, and often times you may not remember exactly what you have changed.

I decided to see what could be done to make make it easier for myself.

The only hard requirement I gave myself is that it must be a single command that can be run from anywhere in my terminal, and should allow me to create a both a 'commit subject' and 'commit body' which is a multi-line commit messages.

Ideally we don't want any dependencies, so that as many people can depend on this as possible.

Implementations

Naive Bash Implementation

This was my first port of call. A simple bash script that mostly gets the job done and is a great way to wireframe out the underlying concept.

See the full version here.

Prerequisites

  • An OpenAI API key
  • jq installed for JSON parsing
  • zsh shell
  • Basic understanding of git

Installation (Bash Version)

  1. Create a bin directory in your home folder if it doesn't exist:
mkdir -p ~/bin
  1. Save this script as smart-commit.zsh in your bin directory: View the complete bash script

  2. Make it executable and add to your PATH:

chmod +x ~/bin/smart-commit.zsh
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

Limitations of Bash Version

While functional, the bash implementation has several limitations:

  • Dependency on zsh shell
  • Requires jq and curl to be installed
  • Issues with parsing multiline responses from OpenAI
  • Less robust error handling

Go Implementation

To address these limitations, I created an improved version in Go. Here's why it's better:

Advantages of Go Version

Dependency Reduction

  • Eliminates the need for jq as JSON handling is native in Go
  • Removes dependency on zsh shell
  • No reliance on external shell commands
  • More portable as it only requires Go runtime

Better Error Handling

  • Type-safe error handling with Go's error system
  • Structured error handling instead of shell exit codes
  • Better stack traces when things go wrong
  • Proper JSON parsing validation

Code Quality

  • Strongly typed data structures for API requests/responses
  • Better code organization with proper function separation
  • More maintainable and testable code
  • IDE support with code completion

Performance

  • Native HTTP client instead of shell curl command
  • More efficient JSON handling without process spawning
  • Reduced system calls
  • Better memory management

Installation (Go Version)

  1. Clone the repository:
git clone https://github.com/positonic/smart-commits
  1. Build the binary:
go build -o smart-commit
  1. Move to your bin directory:
mv smart-commit ~/bin/
  1. Set your OpenAI API key (add to your shell config for persistence):
echo 'export OPENAI_API_KEY="your-key-here"' >> ~/.zshrc
source ~/.zshrc

Technical Details

The Go version includes structured data handling:

type OpenAIRequest struct {
    Model    string    `json:"model"`
    Messages []Message `json:"messages"`
}

type Message struct {
    Role    string `json:"role"`
    Content string `json:"content"`
}

And improved prompt engineering:

Content: "You are a helpful git commit message writer. Given a git diff, write a conventional commit message in this format:\n\n" +
    "<type>: <subject>\n\n" +
    "<detailed description>\n\n" +
    "Rules:\n" +
    "- First line (subject) must be 50 characters or less\n" +
    "- Use conventional commit types (feat, fix, docs, style, refactor, test, chore)\n" +
    "- Add a blank line between subject and description\n" +
    "- Description should explain what and why, not how"

Usage (Both Versions)

Both versions work similarly:

  1. Navigate to your git project:
cd your-project
  1. Make some changes to your files

  2. Run the tool:

smart-commit  # Go version
# or
smart-commit.zsh  # Bash version

I use an alias in my zsh config to make it easier to run:

echo 'alias sc="smart-commit"' >> ~/.zshrc
source ~/.zshrc

and run it with sc

Example Output

$ smart-commit
Generating commit message...

Proposed commit message:
feat: implement user authentication system

Add OAuth2 authentication flow with Google provider.
Include user session management and secure cookie handling.

Do you want to proceed with this commit message? (y/n): y

Successfully committed!

Security Note

Important: Remember to never commit your OpenAI API key to version control! Always keep it in your local environment variables.

Source Code


Found this helpful? Follow me on X/Twitter or check out more of my work on GitHub.

James Farrell