ver Cloud APIs**: Keeps proprietary diffs on-device, eliminates rate limiting, and ensures offline functionality. Ollama's REST API is lightweight and predictable.
2. Modular Function Design: Separates repository validation, staging, LLM invocation, and commit execution. This enables unit testing, easier debugging, and future hook integration.
3. Configurable Parameters: Branch names, model selection, and prompt templates are externalized. Hardcoding master or phi3.5 breaks when teams rename default branches or upgrade models.
4. Defensive Error Handling: Uses set -euo pipefail to fail fast on missing dependencies, Ollama downtime, or Git state conflicts. Prevents partial commits or orphaned staging areas.
Implementation
Create a new utility script named ai-commit.sh. This version replaces the original monolithic structure with explicit functions, improved diff handling, and production-grade error management.
#!/usr/bin/env bash
set -euo pipefail
# Configuration defaults
AI_MODEL="${AI_MODEL:-phi3.5}"
TARGET_BRANCH="${TARGET_BRANCH:-main}"
OLLAMA_ENDPOINT="${OLLAMA_ENDPOINT:-http://localhost:11434}"
PROMPT_TEMPLATE="Generate a concise, imperative-style commit message summarizing these file changes. Focus on purpose and impact. Avoid implementation details. Format: <type>: <description>"
# Utility: Validate Git repository state
validate_repo() {
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "β Error: Not a Git repository." >&2
exit 1
fi
}
# Utility: Check for staged or unstaged changes
check_changes() {
if git diff-index --quiet HEAD -- && git diff --cached --quiet; then
echo "βΉοΈ No changes detected. Exiting."
exit 0
fi
}
# Utility: Stage all modifications and return changed paths
stage_and_list() {
echo "π¦ Staging modifications..."
git add -A
# Extract only file paths for context (avoids diff bloat)
git diff --cached --name-only | tr '\n' ', ' | sed 's/,$//'
}
# Utility: Query Ollama for commit suggestion
invoke_llm() {
local file_context="$1"
local prompt="${PROMPT_TEMPLATE}\nFiles modified: ${file_context}"
echo "π€ Querying ${AI_MODEL} via Ollama..."
# Use curl for explicit endpoint control and timeout handling
local response
response=$(curl -s --max-time 30 "${OLLAMA_ENDPOINT}/api/generate" \
-d "{\"model\":\"${AI_MODEL}\",\"prompt\":\"${prompt}\",\"stream\":false}" 2>/dev/null)
if [[ -z "$response" ]]; then
echo "β οΈ Ollama unreachable or model not loaded. Falling back to manual input." >&2
return 1
fi
# Extract message from JSON response (requires jq or basic parsing)
echo "$response" | grep -o '"response":"[^"]*"' | head -1 | cut -d'"' -f4
}
# Utility: Execute commit with user confirmation
execute_commit() {
local suggested_msg="$1"
local final_msg=""
echo "π‘ Suggested message: ${suggested_msg}"
read -rp "Accept? (y/n/e to edit): " choice
case "$choice" in
[Yy]*) final_msg="$suggested_msg" ;;
[Ee]*)
echo "π Enter commit message (Ctrl+D to finish):"
final_msg=$(cat)
;;
*)
echo "β Commit aborted."
exit 0
;;
esac
if [[ -z "$final_msg" ]]; then
echo "β Empty commit message. Aborting." >&2
exit 1
fi
git commit -m "$final_msg"
echo "β
Committed successfully."
# Optional: Push to remote
read -rp "Push to ${TARGET_BRANCH}? (y/n): " push_choice
if [[ "$push_choice" =~ ^[Yy]$ ]]; then
git push origin "$TARGET_BRANCH"
echo "π Pushed to remote."
fi
}
# Main execution flow
main() {
validate_repo
check_changes
local changed_files
changed_files=$(stage_and_list)
local ai_suggestion
ai_suggestion=$(invoke_llm "$changed_files") || ai_suggestion="feat: update codebase"
execute_commit "$ai_suggestion"
}
main "$@"
Why This Structure Works
set -euo pipefail: Prevents silent failures. If curl times out or git encounters a conflict, the script exits immediately instead of leaving the repository in a half-committed state.
- File-only context extraction: Passing full diffs to LLMs wastes tokens and increases latency. Extracting
--name-only provides sufficient context for accurate summarization while keeping the prompt under 500 tokens.
- Explicit endpoint control: Using
curl instead of ollama run gives precise timeout handling, JSON parsing control, and easier debugging when Ollama is under heavy load.
- Fallback mechanism: If Ollama is unreachable, the script defaults to a generic imperative message rather than failing entirely, ensuring workflow continuity.
Pitfall Guide
1. Blindly Staging Untracked Files
Explanation: git add -A stages everything, including build artifacts, IDE configs, and temporary files. This pollutes commit history and triggers CI failures.
Fix: Use git add -u for tracked files only, or implement a .gitignore audit step. Consider staging selectively via git add -p in interactive mode.
2. Ignoring Ollama Cold-Start Latency
Explanation: Local models load into VRAM/RAM on first invocation. The initial request can take 5β15 seconds, causing developers to assume the script hung.
Fix: Pre-warm the model in a background service or add a startup check: ollama list | grep -q "$AI_MODEL" || ollama pull "$AI_MODEL". Display a spinner or progress indicator during inference.
3. Hardcoding Default Branch Names
Explanation: Assuming master or main breaks when teams use develop, trunk, or feature-specific defaults.
Fix: Dynamically resolve the default branch: git remote show origin | grep 'HEAD branch' | awk '{print $NF}'. Store it in TARGET_BRANCH or read from .git/config.
4. Prompt Context Overflow
Explanation: Large repositories with 50+ changed files can exceed token limits, causing truncated responses or model hallucination.
Fix: Limit context to the first 20 files. Add a summary line: echo "π Context limited to top 20 files. Review manually if needed." before invoking the LLM.
5. NTFS/WSL Permission Mismatches
Explanation: Windows NTFS doesn't natively support Unix executable bits. Scripts copied from WSL or Git Bash may fail with Permission denied despite chmod +x.
Fix: Run chmod +x ai-commit.sh inside the WSL2 terminal, not PowerShell. Alternatively, invoke explicitly: bash ai-commit.sh or create a Git alias that bypasses execution bit checks.
6. Failing to Handle Ollama API Errors
Explanation: Ollama may return HTTP 503 (model loading) or malformed JSON if interrupted. Unhandled responses break the commit flow.
Fix: Validate JSON structure before parsing. Use jq if available, or implement strict regex fallbacks. Add retry logic with exponential backoff for transient failures.
7. Over-Reliance on AI Without Verification
Explanation: Accepting AI suggestions blindly can introduce inaccurate metadata, especially for complex refactors or multi-purpose commits.
Fix: Always present the suggestion for review. Enforce a mandatory y/n/e prompt. Train teams to treat AI output as a draft, not a final artifact.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Solo developer / Open source | Local Ollama pipeline | Zero API cost, full privacy, offline capable | $0 (hardware dependent) |
| Enterprise / Proprietary codebase | Local Ollama + strict review | Keeps code context on-device, meets compliance | $0 (infrastructure only) |
| High-frequency CI/CD pipelines | Cloud API with rate limiting | Faster inference, scalable, managed uptime | $5β$50/month per team |
| Legacy systems / Low RAM | Manual + commitlint | Avoids VRAM/RAM overhead, deterministic | $0 (developer time only) |
| Multi-language monorepo | Local Ollama + selective staging | Handles diverse file types, reduces context noise | $0 (requires prompt tuning) |
Configuration Template
Create a .ai-commit.env file in your project root or home directory to externalize settings:
# .ai-commit.env
AI_MODEL="phi3.5"
OLLAMA_ENDPOINT="http://localhost:11434"
TARGET_BRANCH="main"
PROMPT_TEMPLATE="Generate a concise, imperative-style commit message. Focus on purpose and impact. Avoid implementation details. Format: <type>: <description>"
MAX_CONTEXT_FILES=20
TIMEOUT_SECONDS=30
Load it in the script before execution:
if [[ -f ".ai-commit.env" ]]; then
source ".ai-commit.env"
elif [[ -f "$HOME/.ai-commit.env" ]]; then
source "$HOME/.ai-commit.env"
fi
Quick Start Guide
- Install Ollama: Download from
ollama.ai, run ollama pull phi3.5, and verify with ollama list.
- Deploy the script: Save
ai-commit.sh to ~/bin, run chmod +x ~/bin/ai-commit.sh, and add export PATH="$HOME/bin:$PATH" to your shell profile.
- Initialize configuration: Create
~/.ai-commit.env with your preferred model, branch, and prompt template.
- Test the workflow: Navigate to any Git repository, make a change, and run
ai-commit.sh. Accept or edit the suggestion, then push.
- Optional Git alias: Run
git config --global alias.ai '!bash ~/bin/ai-commit.sh' to invoke via git ai from any directory.
This pipeline transforms commit generation from a manual bottleneck into a deterministic, context-aware process. By keeping inference local, enforcing structured prompts, and maintaining human-in-the-loop validation, teams gain consistent metadata without sacrificing privacy or workflow speed.