Skip to content

Commit e079b9a

Browse files
authored
Add files via upload
1 parent 251df05 commit e079b9a

1 file changed

Lines changed: 101 additions & 0 deletions

File tree

auto_commit.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import subprocess
2+
from ollama import chat
3+
from ollama import ChatResponse
4+
5+
model = "gemma3:4b"
6+
prompt = f"""
7+
Given the following Git diff and the list of changed files (with file types), suggest a single concise and relevant commit message that best summarizes all the changes made. Use a conventional commit style (e.g., feat:, fix:, chore:, docs:, refactor:). The message should be no longer than 72 characters.
8+
Just return the commit messages without any additional text or explanation.
9+
Input:
10+
Git Diff:
11+
[Git Diff]
12+
13+
Changed Files and Types:
14+
[Changed Files and Types]
15+
16+
Instructions:
17+
1. Analyze the diff and the list of changed files/types.
18+
2. Summarize all changes into a single logical commit.
19+
3. Write a concise commit message (max 72 characters) in the conventional commit style
20+
"""
21+
22+
def get_changed_files():
23+
# Get all staged and unstaged files (excluding untracked)
24+
result = subprocess.run(
25+
["git", "diff", "--name-only"],
26+
capture_output=True, text=True
27+
)
28+
unstaged = set(result.stdout.splitlines())
29+
result = subprocess.run(
30+
["git", "diff", "--name-only", "--staged"],
31+
capture_output=True, text=True
32+
)
33+
staged = set(result.stdout.splitlines())
34+
# Union of both sets
35+
return sorted(unstaged | staged)
36+
37+
def get_diff_for_file(filename, staged=False):
38+
cmd = ["git", "diff"]
39+
if staged:
40+
cmd.append("--staged")
41+
cmd.append("--")
42+
cmd.append(filename)
43+
result = subprocess.run(cmd, capture_output=True, text=True)
44+
return result.stdout
45+
46+
def get_commit_messages(diff, files):
47+
# Use the Ollama chat model to get commit messages
48+
if len(diff) == 0 or len(files) == 0:
49+
return ""
50+
try:
51+
response: ChatResponse = chat(model=model, messages=[
52+
{
53+
'role': 'user',
54+
'content': prompt.replace("[Git Diff]", diff).replace("[Changed Files and Types]", files),
55+
},
56+
])
57+
return response['message']['content']
58+
except Exception:
59+
return ""
60+
61+
def diff_single_file(file):
62+
print(f"{file}")
63+
commit_messages = []
64+
unstaged_diff = get_diff_for_file(file, staged=False).strip()
65+
staged_diff = get_diff_for_file(file, staged=True).strip()
66+
messages_staged_diff = get_commit_messages(staged_diff, file).strip()
67+
messages_unstaged_diff = get_commit_messages(unstaged_diff, file).strip()
68+
if messages_staged_diff:
69+
commit_messages.append(messages_staged_diff)
70+
if messages_unstaged_diff:
71+
commit_messages.append(messages_unstaged_diff)
72+
return commit_messages
73+
""
74+
def git_commit_everything(message):
75+
"""
76+
Stages all changes (including new, modified, deleted files), commits with the given message,
77+
and pushes the commit to the current branch on the default remote ('origin').
78+
"""
79+
# Stage all changes (new, modified, deleted)
80+
subprocess.run(['git', 'add', '-A'], check=True)
81+
# Commit with the provided message
82+
subprocess.run(['git', 'commit', '-m', message], check=True)
83+
84+
def main():
85+
files = get_changed_files()
86+
if not files:
87+
print("No changes detected.")
88+
return
89+
90+
all_commit_messages = []
91+
for file in files:
92+
commit_messages = diff_single_file(file)
93+
all_commit_messages.extend(commit_messages)
94+
95+
print("Suggested commit messages:")
96+
single_message = "\n".join(all_commit_messages)
97+
print(single_message)
98+
git_commit_everything(single_message)
99+
100+
if __name__ == "__main__":
101+
main()

0 commit comments

Comments
 (0)