Skip to content

Commit a2509cd

Browse files
committed
Automate commit & push with Ollama/Mistral AI
1 parent 6fc49ae commit a2509cd

File tree

1 file changed

+51
-69
lines changed

1 file changed

+51
-69
lines changed

git-commit-push-script.sh

Lines changed: 51 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
## Automating Staging, Committing and Pushing to GitHub with Ollama and Mistral AI 👨🏻‍💻➡️
2-
## AI commits generated from git diff
3-
## Configuration instructions: https://github.com/wesleyscholl/git-commit-push-script
4-
51
#!/bin/bash
62
source ~/.bash_profile
73

8-
# Pre-warm the model (optional - keeps it loaded)
9-
ollama run mistral-commit "test" > /dev/null 2>&1 &
4+
# Configuration
5+
MAX_DIFF_CHARS=2000 # Truncate diff to prevent long processing
6+
TIMEOUT_SECONDS=10 # Max time to wait for LLM response
7+
MAX_COMMIT_LENGTH=50 # Max characters for commit message
108

119
# Stage all changes
1210
git add -A
@@ -22,79 +20,63 @@ echo "Default branch: $default_branch"
2220
# Extract Jira ticket number from current directory
2321
ticket=$(echo $base_branch | grep -o -E '([A-Za-z]+-[0-9]{3,}|[A-Za-z]+-[0-9]{3,})')
2422

25-
# Get the git diff comparing the current branch with the default branch
26-
diff=$(git diff origin/$default_branch)
27-
# echo "Git diff:\n\n$diff"
28-
29-
# # Default model (change if desired)
30-
# MODEL="mistral-commit"
31-
32-
# # Prepare the prompt
33-
# PROMPT="$diff"
34-
35-
# # Run the model and capture output
36-
# COMMIT_MSG=$(ollama run "$MODEL" "$PROMPT")
37-
38-
# # If the commit message is empty, exit with an error
39-
# if [ -z "$COMMIT_MSG" ]; then
40-
# echo "Error: Commit message is empty. Please check the diff and try again."
41-
# exit 1
42-
# fi
43-
44-
# Stringify the diff
45-
# diff=$(echo $diff | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed 's/\n/\\n/g')
46-
47-
# Default model (change if desired)
48-
MODEL="gemma3:4b"
49-
50-
# Prepare the prompt
51-
PROMPT=$(printf "You are an expert software engineer and technical writer. Write a clear, professional commit message based on the following Git diff. Requirements:\n- Summarize the purpose and key changes made, like if a file was created, edited, moved or deleted.\n- Include which files were created, modified, deleted (removed), or moved if applicable.\n- Do NOT include quotes, explanations, diff syntax, markdown formatting, or any additional text or formatting.\n- Limit your response to 20 tokens.\n\n Respond in the following format:\nCommit message: <Your concise commit message>\n\nGit diff:\n%s" "$diff")
23+
# Get changed files for fallback message
24+
changed_files=$(git diff --name-only origin/$default_branch | head -3)
25+
first_file=$(echo "$changed_files" | head -1)
26+
file_count=$(git diff --name-only origin/$default_branch | wc -l | tr -d ' ')
5227

53-
# Run the model and capture output
54-
commit_message=$(echo "$PROMPT" | ollama run "$MODEL")
55-
56-
# Prepare the Gemini API request
57-
# gemini_request='{"contents":[{"parts":[{"text": "Write a git commit message title (no more than 72 characters total) for the following git diff: '"$diff"' Do not include any other text in the repsonse."}]}]}'
58-
59-
# # Get commit message from Gemini API
60-
# commit_message=$(curl -s \
61-
# -H 'Content-Type: application/json' \
62-
# -d "$gemini_request" \
63-
# -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${GEMINI_API_KEY}" \
64-
# | jq -r '.candidates[0].content.parts[0].text'
65-
# )
66-
67-
# # Clean up commit message formatting - remove #, ```, "", '', ()), and period . at the end of response
68-
commit_message=$(echo $commit_message | sed 's/#//g' | sed 's/```//g' | sed 's/Commit message title://g' | sed 's/Commit message summary://g' | sed 's/\.//g' | sed 's/\"//g' | sed "s/'//g" | sed 's/())//g' | sed 's/()//g' | sed 's/Commit message://g' | sed 's/Commit message title: //g' | sed 's/Commit message summary: //g' | sed 's/Commit message body: //g' | sed 's/Commit message body://g' | sed 's/^\s*//;s/\s*$//' | sed 's/Code Review Request://g' | sed 's/Code Review://g' | sed 's/Summary of changes://g')
28+
# Generate fallback message based on changes
29+
if [ "$file_count" -eq 1 ]; then
30+
fallback_message="${first_file} updated"
31+
elif [ "$file_count" -gt 1 ]; then
32+
fallback_message="${first_file} and $((file_count - 1)) other file(s) updated"
33+
else
34+
fallback_message="Updated ${base_branch} branch"
35+
fi
6936

70-
echo $commit_message
37+
# Get the git diff - truncate for performance
38+
diff=$(git diff origin/$default_branch | head -c $MAX_DIFF_CHARS)
7139

72-
if [ -z "$commit_message" ]; then
73-
echo "Error: API request for commit message failed. Please try again."
74-
exit 1
40+
# Skip LLM if diff is too large (use fallback)
41+
diff_size=$(git diff origin/$default_branch | wc -c | tr -d ' ')
42+
if [ "$diff_size" -gt 10000 ]; then
43+
echo "Large diff detected ($diff_size chars). Using fallback message."
44+
commit_message="$fallback_message"
45+
else
46+
# Default model
47+
MODEL="gemma3:4b"
48+
49+
# Optimized prompt - shorter, more direct
50+
PROMPT="Git commit message (max 50 chars, no quotes/formatting):
51+
$(echo "$diff" | head -50)"
52+
53+
# Run model with timeout
54+
commit_message=$(echo "$PROMPT" | timeout $TIMEOUT_SECONDS ollama run "$MODEL" --verbose 2>/dev/null | head -1)
55+
56+
# Check if timeout occurred or empty response
57+
if [ $? -eq 124 ] || [ -z "$commit_message" ]; then
58+
echo "LLM timeout or empty response. Using fallback message."
59+
commit_message="$fallback_message"
60+
fi
7561
fi
7662

77-
# # Clean up commit message formatting - remove #, ```, "", '', ()), and period . at the end of response
78-
# commit_message=$(echo $COMMIT_MSG | sed 's/#//g' | sed 's/```//g' | sed 's/Commit message title://g' | sed 's/Commit message summary://g' | sed 's/\.//g' | sed 's/\"//g' | sed "s/'//g" | sed 's/())//g' | sed 's/()//g' | sed 's/Commit message://g' | sed 's/Commit message title: //g' | sed 's/Commit message summary: //g' | sed 's/Commit message body: //g' | sed 's/Commit message body://g')
63+
# Clean up commit message formatting
64+
commit_message=$(echo "$commit_message" | sed 's/#//g' | sed 's/```//g' | sed 's/Commit message://gi' | sed 's/\.//g' | sed 's/\"//g' | sed "s/'//g" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
7965

80-
# # If the commit message is longer than 72 characters, truncate at the last word boundary
81-
# if [ ${#commit_message} -gt 72 ]; then
82-
# commit_message=$(echo $commit_message | cut -d' ' -f1-18)
83-
# fi
66+
# Truncate to max length at word boundary
67+
if [ ${#commit_message} -gt $MAX_COMMIT_LENGTH ]; then
68+
commit_message=$(echo "$commit_message" | cut -c1-$MAX_COMMIT_LENGTH | sed 's/[[:space:]][^[:space:]]*$//')
69+
fi
8470

85-
# Echo the commit message
86-
# echo $commit_message
71+
echo "Commit message: $commit_message"
8772

88-
# $commit_message == null ? commit_message="Updated ${base_branch} branch" : echo "Commit message: $commit_message"
89-
# Check for null commit message and set a default if necessary
90-
if [ "$commit_message" == "null" ] || [ -z "$commit_message" ]; then
91-
commit_message="Updated ${base_branch} branch"
92-
echo "Commit message is null or empty. Using default: $commit_message"
93-
else
94-
echo "Commit message: $commit_message"
73+
# Final fallback check
74+
if [ -z "$commit_message" ] || [ "$commit_message" == "null" ]; then
75+
commit_message="$fallback_message"
76+
echo "Using fallback: $commit_message"
9577
fi
9678

97-
# Set the GIT_SSH_PASSPHRASE environment variables
79+
# Set the environment variables
9880
export COMMIT_MESSAGE="$commit_message"
9981
export TICKET="$ticket"
10082

0 commit comments

Comments
 (0)