-
-
Save laurentperrinet/176591df03d272fa7a2d14892c4a2622 to your computer and use it in GitHub Desktop.
🤖 Generate git commit messages automatically using local LLM (Ollama). Simple bash script that analyzes your git diff and creates meaningful commit messages. Runs locally 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
| #!/bin/bash | |
| OLLAMA_MODEL="gpt-oss:120b-cloud" | |
| ASK_PULL=false | |
| ASK_PUSH=false | |
| TARGETS=() | |
| show_help() { | |
| cat <<EOF | |
| An auto-commit tool in bash using Ollama | |
| https://gist.github.com/laurentperrinet/176591df03d272fa7a2d14892c4a2622 | |
| Usage: $(basename "$0") [options] [path1] [path2] ... | |
| Options: | |
| -a, --ask-pull Ask before running 'git pull' (interactive) | |
| -p, --ask-push Ask before running 'git push' (interactive) | |
| -m, --model <name> Use a specific Ollama model (default: gpt-oss:120b-cloud) | |
| -h, --help Show this help and exit | |
| If one or more paths are provided, only those paths will be staged and committed. | |
| If no paths are given, the script keeps the original behavior (git add -u). | |
| If --ask-pull is not given, the script runs 'git pull' automatically. | |
| EOF | |
| } | |
| # Parse args: optional flags and one or more paths | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -a|--ask-pull) ASK_PULL=true; shift ;; | |
| -p|--ask-push) ASK_PUSH=true; shift ;; | |
| # NEW: Parse the --model flag and its argument | |
| -m|--model) | |
| if [[ -n "$2" ]]; then | |
| OLLAMA_MODEL="$2" | |
| shift 2 # Consume the flag and its argument | |
| else | |
| echo "Error: --model requires a model name as an argument." | |
| show_help | |
| exit 1 | |
| fi | |
| ;; | |
| -h|--help) show_help; exit 0 ;; | |
| --) shift; break ;; | |
| -*) | |
| echo "Unknown option: $1" | |
| show_help | |
| exit 1 | |
| ;; | |
| *) | |
| # Append all non-flag arguments to the TARGETS array. | |
| TARGETS+=("$1") | |
| shift | |
| ;; | |
| esac | |
| done | |
| if [[ "$ASK_PULL" == "true" ]]; then | |
| echo -e "\nShould I git pull first? (Y/n)" | |
| read answer | |
| if [[ -z "$answer" || "$answer" =~ ^[Yy]$ ]]; then | |
| git pull | |
| fi | |
| else | |
| echo "Running 'git pull' (no prompt)..." | |
| git pull | |
| fi | |
| # MODIFICATION: The staging logic is updated to handle multiple paths. | |
| # It checks if the TARGETS array has any elements. | |
| if [[ ${#TARGETS[@]} -gt 0 ]]; then | |
| echo "Staging specified paths: ${TARGETS[*]}" | |
| # -A ensures new, modified and deleted files under the paths are staged. | |
| # "${TARGETS[@]}" correctly expands the array, handling filenames with spaces. | |
| git add -A -- "${TARGETS[@]}" | |
| else | |
| echo "Staging all modified/deleted files (git add -u)..." | |
| git add -u | |
| fi | |
| git diff --cached > /tmp/git_diff.txt | |
| # If there's no diff, exit | |
| if [ ! -s /tmp/git_diff.txt ]; then | |
| echo "No staged changes to commit" | |
| exit 1 | |
| fi | |
| cat /tmp/git_diff.txt | |
| # Create the prompt with the diff content, escaping special characters | |
| diff_content=$(sed 's/"/\\"/g; s/\\/\\\\/g; s/`/\\`/g' /tmp/git_diff.txt) | |
| prompt="You are a scientific pragrammer writing code in computational neuroscience, artificial intelligence and machine learning. Given the following git diff, write a clear and concise git commit message that summarizes the changes.\n\nREQUIREMENTS:\n- Focus on WHAT changed and WHY. Use present tense, imperative mood. Keep it under 72 characters for the first line, then add more details after a blank line. Use present tense, imperative mood ('Add', 'Fix', 'Update', not 'Added', 'Fixed'). Remember to keep the first line under 72 characters\n- Focus exclusively on WHAT changed and WHY\n- Do not add opinions, suggestions for improvements, or commentary beyond the changes shown\n- Detect and explicitly mention file operations: renames, deletions, moves, additions\n- Add detail after a blank line only if necessary to explain the context of the changes\n\nFORMAT:\n[Action] [Subject] - [File operations if applicable]\n\n[Optional detailed explanation of WHY these changes were made]\n\nFILE OPERATIONS TO DETECT:\n- File renamed: 'Rename X to Y'\n- File deleted: 'Remove X'\n- File moved: 'Move X from A to B'\n- Multiple files: 'Refactor module files: rename handler.js, move utils.js'\n\nOUTPUT ONLY THE COMMIT MESSAGE. DO NOT INCLUDE ANY OTHER TEXT, ANALYSIS, OR RECOMMENDATIONS. DO NOT WRITE ANYTHING LONGER THAN 5000 WORDS. \n\nGIT DIFF:\n\n$diff_content" | |
| # Run the prompt through ollama and save the response | |
| ollama run "$OLLAMA_MODEL" --hidethinking "$prompt" > /tmp/commit_msg.txt | |
| # Show the proposed commit message and ask for confirmation | |
| echo -e "\nProposed commit message:" | |
| echo "------------------------" | |
| cat /tmp/commit_msg.txt | |
| echo "------------------------" | |
| echo -e "\nDo you want to proceed with this commit message? (Y/n)" | |
| read answer | |
| if [[ -z "$answer" || "$answer" =~ ^[Yy]$ ]]; then | |
| # Perform the commit using the generated message | |
| git commit -F /tmp/commit_msg.txt | |
| echo "Changes committed successfully!" | |
| else | |
| echo "Commit canceled" | |
| fi | |
| # Clean up temporary files | |
| rm /tmp/git_diff.txt /tmp/commit_msg.txt | |
| if [[ "$ASK_PUSH" == "true" ]]; then | |
| echo -e "\nShould I git push now? (Y/n)" | |
| read answer | |
| if [[ -z "$answer" || "$answer" =~ ^[Yy]$ ]]; then | |
| git push | |
| fi | |
| else | |
| echo "Running 'git push' (no prompt)..." | |
| git push | |
| fi | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment