Automate git commit messages with a simple bash script and openrouter
Published: May 12, 2025
I like to automate as much work as possible. Here's a simple shell / bash script I'm using to save time by automatically creating git commit messages.
3 steps to get this to work:
- Sign up for Openrouter (A unified API for LLM models)
- Add your OPENROUTER_API_KEY to your environment variables (or paste it directly into the script below, replacing $OPENROUTER_API_KEY)
- Add the below script to your ~/.bash_aliases or ~/.bashrc or equivalent
Refresh your terminal and you're good to go.
You can now generate AI commit messages automatically by typing gca
into your terminal.
Video guide for the below:
function gca() {local commit_message="$1"local push_remote="$2"# Check if Git is installedif ! command -v git &> /dev/null; thenecho "Git is not installed. Please install Git and try again."return 1fi# Check if jq is installedif ! command -v jq &> /dev/null; thenecho "jq is not installed. Please install jq and try again."return 1fi# Get the current Git repositorylocal repo=$(git rev-parse --show-toplevel 2> /dev/null)if [ -z "$repo" ]; thenecho "Not a Git repository. Please navigate to a Git repository and try again."return 1fi# Check for manual commit message. If provided, use it and exit.if [ -n "$commit_message" ]; thenecho "Using manual commit message: $commit_message"git add --allgit commit -am "$commit_message"[ -n "$push_remote" ] && git push origin HEADreturn 0fi# Get the diff of the modified files (staged and unstaged)local diff=$(git diff HEAD)if [ -z "$diff" ]; thenecho "No changes to commit."return 0fi# Escape the diff for JSONlocal escaped_diff=$(echo "$diff" | jq -Rs .)if [ $? -ne 0 ]; thenecho "Failed to escape diff content"return 1filocal system_message="You are a master programmer who generates concise and informative Git commit messages. Explain why we have made the changes. If I remove a TODO, mention if the commit completed the task. Write a "local user_message=$(printf "Write a concise Git commit message for the following changes: Diff: %s. Only output the commit message, no other text. Use plain language to explain why the changes were made. You must exclude any formatting characters such as \`\`\` from your output. The first character of your output must be a capital letter. Write in highly succinct sentences. Never use the word 'Refactor'." "$escaped_diff")# Construct the JSON payload using jqlocal json_data=$(jq -n \--arg sm "$system_message" \--arg um "$user_message" \'{"model": "google/gemini-2.0-flash-lite-001","messages": [{"role": "system", "content": $sm},{"role": "user", "content": $um}]}')if [ $? -ne 0 ]; thenecho "Failed to construct JSON payload"return 1fi# Make the API calllocal api_response=$(curl --silent --show-error "https://openrouter.ai/api/v1/chat/completions" \-X POST \-H "Content-Type: application/json" \-H "Authorization: Bearer $OPENROUTER_API_KEY" \-d "$json_data")# Check if the API call was successfulif [ $? -ne 0 ]; thenecho "Error calling the API. Please check your internet connection and try again."return 1fiecho "API Response: $api_response"echo "\n\n"# Extract the commit message using jqlocal commit_message=$(jq -r ".choices[0].message.content" <<< "$api_response")# Check if the commit message is empty or nullif [ -z "$commit_message" ]; thenecho "Failed to generate a commit message."echo "API response: $api_response"return 1fi# Stage and commit all files (staged and unstaged)echo "Message: $commit_message"git add --allgit commit -am "$commit_message"# Push to remote if specified[ -n "$push_remote" ] && git push origin HEADreturn 0}alias gca=gca
The model is set to Gemini 2 Flash Lite. This is a model that's smart enough for creating commit messages, and which is cheap and fast enough not to interrupt your git flow.