Skip to content

Commit b8a6fa9

Browse files
committed
Allow generating commit message via ollama
Use an large language model (via ollama) to generate commit message that match commit style by learning from previous commits. Currently, qwen2.5-coder is used for commit message generation, code reasoning, and suggestions. Change-Id: Iaf4b1952a3e14bbdd4c832aa4a93753f7ca11473
1 parent a1db6c5 commit b8a6fa9

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

scripts/aspell-pws

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,5 @@ typedef
350350
BitInt
351351
noreturn
352352
pragma
353+
ollama
354+
qwen

scripts/prepare-commit-msg.hook

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ COMMIT_MSG_FILE="$1"
44

55
# If the commit message file already contains non-comment lines, do nothing.
66
if grep -qE '^[^[:space:]#]' "$COMMIT_MSG_FILE"; then
7-
exit 0
7+
exit 0
88
fi
99

1010
# Gather a list of staged (changed) files.
@@ -34,6 +34,119 @@ INLINE_MSG=$(cat <<'EOF'
3434
EOF
3535
)
3636

37+
# AICommit uses an LLM (via ollama) to generate commit messages that match git
38+
# commit style by learning from previous commits.
39+
# Inspired by https://github.com/acrosa/aicommits.
40+
MODEL="qwen2.5-coder"
41+
SUGGESTED_COMMITMSG=
42+
AICOMMIT=$(git config --get core.aicommit || echo 'auto')
43+
if [[ "$AICOMMIT" == "always" ]] || [[ "$AICOMMIT" == "auto" && -t 1 ]] && \
44+
git diff --cached --name-only | grep -qiE "\.(c|h|cpp|hpp)$"; then
45+
# Build commit history list from the last non-merge commit messages.
46+
commit_history=$(git log -n 70 --no-merges --pretty=format:'"%s",' | \
47+
sed -E 's/ \(\#[0-9]+\)//; $ s/,$//')
48+
commit_history="[$commit_history]"
49+
50+
# Capture the staged diff.
51+
staged_diff=$(git diff --cached)
52+
53+
# Create a style prompt from commit history.
54+
style_prompt="
55+
You are a specialized system for generating high-quality Git commit messages based on 'git diff --cached' output and optional developer descriptions.
56+
# Task:
57+
Analyze the following commit messages and produce **accurate, concise, and meaningful commit messages** that clearly describe the changes:
58+
- $commit_history
59+
60+
# Output:
61+
Provide a concise description of the style without quoting commit content.
62+
"
63+
echo "Running ollama... "
64+
style_description=$(echo "$style_prompt" | ollama run "$MODEL")
65+
66+
# Build the commit message prompt.
67+
prompt="
68+
# Context:
69+
Style: $style_description
70+
71+
# Instructions:
72+
- Analyze the diff below and generate a commit message based solely on its content.
73+
- Mimic the style described above (tone, length, structure) without copying previous messages.
74+
- Use clear action verbs and be concise.
75+
- Output ONLY the commit message (subject, a blank line, then body).
76+
- Separate the subject from the body with a blank line.
77+
- Remove triple backticks; replace backticks with single quotes.
78+
- Keep the first line (subject) under 50 characters
79+
- Ensure no line exceeds 72 characters.
80+
- Avoid vague messages like 'Updates' or 'Fixed bug'
81+
- Always write in **plain text** without markdown or HTML.
82+
- No concluding remarks.
83+
- Do NOT use conventional commit prefixes (like 'feat:', 'fix:', 'docs:')
84+
- Avoid the redundant message like 'Updated commit messages'
85+
86+
# Diff:
87+
<diff>$staged_diff</diff>
88+
89+
Commit message:"
90+
if [ "$2" = "--show-prompt" ]; then
91+
echo "Full style prompt:"
92+
echo "$style_prompt"
93+
echo "Extracted style:"
94+
echo "$style_description"
95+
echo "Full commit prompt:"
96+
echo "$prompt"
97+
fi
98+
99+
# Generate commit message using ollama.
100+
SUGGESTED_COMMITMSG=$(echo "$prompt" | ollama run "$MODEL")
101+
102+
# Post-process the commit message.
103+
# - Trim whitespace.
104+
# - Remove triple backticks.
105+
# - Replace backticks with single quotes.
106+
# - Wrap lines at 72 characters.
107+
SUGGESTED_COMMITMSG=$(echo "$SUGGESTED_COMMITMSG" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
108+
SUGGESTED_COMMITMSG=$(echo "$SUGGESTED_COMMITMSG" | sed -E '/^(Author:|Date:|Commit message:)/d')
109+
SUGGESTED_COMMITMSG="$(
110+
echo "$SUGGESTED_COMMITMSG" \
111+
| sed -E '/^```(markdown|diff|text|plaintext)?$/d; s/\*\*([^*]+)\*\*/\1/g; s/`([^`]+)`/'\''\1'\''/g' \
112+
| awk -v w=72 '
113+
function sp(n){ return sprintf("%" n "s", "") }
114+
function wrap(bp, txt){
115+
gsub(/^ +| +$/,"",txt)
116+
if(!length(txt)){ print bp; return }
117+
n = split(txt, a, /[ \t]+/)
118+
l = bp; len = length(bp)
119+
for(i = 1; i <= n; i++){
120+
wl = length(a[i])
121+
if((len > length(bp) ? len + 1 : len) + wl > w){
122+
print l; l = sp(length(bp)) a[i]; len = length(bp) + wl
123+
} else if(len == length(bp)){
124+
l = bp a[i]; len = length(bp) + wl
125+
} else {
126+
l = l " " a[i]; len++; len += wl
127+
}
128+
}
129+
if(len > length(bp)) print l
130+
}
131+
BEGIN { paragraph = ""; bullet = "" }
132+
{
133+
line = $0; gsub(/^ +| +$/, "", line)
134+
if(!length(line)){
135+
if(length(paragraph)){ wrap(bullet, paragraph); paragraph = ""; bullet = "" }
136+
print ""; next
137+
}
138+
if(match(line, /^( *[0-9]+\.[ \t]+| *-[ \t]+| *\*[ \t]+)/)){
139+
if(length(paragraph)){ wrap(bullet, paragraph); paragraph = ""; bullet = "" }
140+
bp = substr(line, RSTART, RLENGTH); rest = substr(line, RSTART + RLENGTH)
141+
gsub(/^[ \t]+/, "", rest); wrap(bp, rest)
142+
} else {
143+
if(!length(paragraph)) paragraph = line; else paragraph = paragraph " " line
144+
}
145+
}
146+
END { if(length(paragraph)) wrap(bullet, paragraph) }
147+
')"
148+
fi
149+
37150
# Write an empty line, the guidelines, and the changed files into the commit message.
38151
{
39152
echo
@@ -44,6 +157,11 @@ EOF
44157
else
45158
echo "# (No staged files detected.)"
46159
fi
160+
if [ -n "$SUGGESTED_COMMITMSG" ]; then
161+
echo "#"
162+
echo "# ✅Suggested commit messages:"
163+
echo "$SUGGESTED_COMMITMSG" | sed 's/^/# /'
164+
fi
47165
} > "$COMMIT_MSG_FILE"
48166

49167
# Prompt the user about aborting the commit.

0 commit comments

Comments
 (0)