Created
January 30, 2026 12:09
-
-
Save banyudu/25de089e4690d50f912c0e43f9568708 to your computer and use it in GitHub Desktop.
Auto generate git commit message with ollama
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # git-auto-commit - Auto-generate commit messages using local LLM via Ollama | |
| # | |
| # Usage: git-auto-commit [options] | |
| # Options: | |
| # -m, --model MODEL Model to use (default: qwen2.5:3b) | |
| # --no-push Skip auto-push after commit | |
| # -n, --no-author Don't add AI co-author | |
| # -d, --dry-run Show message without committing | |
| # -h, --help Show this help | |
| # | |
| # By default, this script will: | |
| # - Auto-stage all changes (git add -A) | |
| # - Auto-push after commit | |
| # | |
| # Supported models (via Ollama): | |
| # - qwen2.5:3b (fast, recommended) | |
| # - qwen2.5:7b (better quality) | |
| # - gemma2:2b (very fast) | |
| # - gemma2:9b (better quality) | |
| # - llama3.2:3b (fast) | |
| # - mistral:7b (balanced) | |
| # | |
| # Requirements: | |
| # - Ollama running locally (ollama serve) | |
| # - curl, jq | |
| # | |
| set -e | |
| # Colors | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' | |
| # Default settings | |
| MODEL="${GIT_COMMIT_MODEL:-qwen2.5:3b}" | |
| OLLAMA_HOST="${OLLAMA_HOST:-http://localhost:11434}" | |
| PUSH_AFTER=true | |
| ADD_AI_AUTHOR=true | |
| DRY_RUN=false | |
| print_status() { echo -e "${GREEN}✓${NC} $1"; } | |
| print_info() { echo -e "${BLUE}ℹ${NC} $1"; } | |
| print_warning() { echo -e "${YELLOW}⚠${NC} $1"; } | |
| print_error() { echo -e "${RED}✗${NC} $1"; } | |
| show_help() { | |
| head -28 "$0" | tail -26 | sed 's/^#//' | sed 's/^ //' | |
| exit 0 | |
| } | |
| # Parse arguments | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| -m|--model) | |
| MODEL="$2" | |
| shift 2 | |
| ;; | |
| --no-push) | |
| PUSH_AFTER=false | |
| shift | |
| ;; | |
| -n|--no-author) | |
| ADD_AI_AUTHOR=false | |
| shift | |
| ;; | |
| -d|--dry-run) | |
| DRY_RUN=true | |
| shift | |
| ;; | |
| -h|--help) | |
| show_help | |
| ;; | |
| *) | |
| print_error "Unknown option: $1" | |
| show_help | |
| ;; | |
| esac | |
| done | |
| # Check dependencies | |
| check_deps() { | |
| local missing=() | |
| command -v curl >/dev/null || missing+=("curl") | |
| command -v jq >/dev/null || missing+=("jq") | |
| command -v git >/dev/null || missing+=("git") | |
| if [[ ${#missing[@]} -gt 0 ]]; then | |
| print_error "Missing dependencies: ${missing[*]}" | |
| exit 1 | |
| fi | |
| } | |
| # Check if Ollama is running | |
| check_ollama() { | |
| if ! curl -s "${OLLAMA_HOST}/api/tags" >/dev/null 2>&1; then | |
| print_error "Ollama is not running at ${OLLAMA_HOST}" | |
| print_info "Start it with: ollama serve" | |
| exit 1 | |
| fi | |
| } | |
| # Auto-stage and get diff | |
| get_staged_diff() { | |
| # Auto-stage all changes | |
| print_info "Auto-staging changes..." | |
| git add -A | |
| local diff | |
| diff=$(git diff --cached --stat 2>/dev/null) | |
| if [[ -z "$diff" ]]; then | |
| print_warning "No changes to commit" | |
| exit 0 | |
| fi | |
| # Get detailed diff (truncate if too large for speed) | |
| local full_diff | |
| full_diff=$(git diff --cached 2>/dev/null | head -500) | |
| echo "$full_diff" | |
| } | |
| # Generate commit message using Ollama | |
| generate_commit_message() { | |
| local diff="$1" | |
| local prompt="Generate a concise git commit message for these changes. | |
| Rules: | |
| - Use conventional commit format: type(scope): description | |
| - Types: feat, fix, refactor, docs, style, test, chore | |
| - Keep the first line under 72 characters | |
| - Be specific but brief | |
| - No quotes around the message | |
| Changes: | |
| $diff | |
| Commit message:" | |
| # Use Ollama's generate API (faster than chat for simple tasks) | |
| local response | |
| response=$(curl -s "${OLLAMA_HOST}/api/generate" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$(jq -n --arg model "$MODEL" --arg prompt "$prompt" '{ | |
| model: $model, | |
| prompt: $prompt, | |
| stream: false, | |
| options: { | |
| temperature: 0.3, | |
| num_predict: 100 | |
| } | |
| }')" 2>/dev/null) | |
| if [[ -z "$response" ]]; then | |
| print_error "Failed to get response from Ollama" | |
| exit 1 | |
| fi | |
| # Extract the response text | |
| local message | |
| message=$(echo "$response" | jq -r '.response // empty' | head -1 | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//') | |
| # Clean up the message (remove quotes if present) | |
| message=$(echo "$message" | sed 's/^["'"'"']//; s/["'"'"']$//') | |
| # Fallback if empty | |
| if [[ -z "$message" ]]; then | |
| message="chore: update files" | |
| fi | |
| echo "$message" | |
| } | |
| # Main | |
| main() { | |
| check_deps | |
| check_ollama | |
| print_info "Using model: ${MODEL}" | |
| # Auto-stage and get changes | |
| local diff | |
| diff=$(get_staged_diff) | |
| # Show what's staged | |
| echo -e "${BLUE}Changes to commit:${NC}" | |
| git diff --cached --stat | head -20 | |
| echo "" | |
| # Generate commit message | |
| print_info "Generating commit message..." | |
| local message | |
| message=$(generate_commit_message "$diff") | |
| echo -e "${GREEN}Generated message:${NC} $message" | |
| echo "" | |
| if $DRY_RUN; then | |
| print_info "Dry run - not committing" | |
| exit 0 | |
| fi | |
| # Build commit command | |
| local commit_args=(-m "$message") | |
| # Add AI co-author | |
| if $ADD_AI_AUTHOR; then | |
| commit_args+=(-m "Co-Authored-By: Claude <claude@anthropic.com>") | |
| fi | |
| # Commit | |
| if git commit "${commit_args[@]}"; then | |
| print_status "Committed successfully!" | |
| else | |
| print_error "Commit failed" | |
| exit 1 | |
| fi | |
| # Push if requested | |
| if $PUSH_AFTER; then | |
| print_info "Pushing to remote..." | |
| if git push; then | |
| print_status "Pushed successfully!" | |
| else | |
| print_warning "Push failed - you may need to set upstream" | |
| fi | |
| fi | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment