git-commit-message 0.7.0__tar.gz → 0.8.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/PKG-INFO +109 -45
- git_commit_message-0.8.1/README.md +212 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/pyproject.toml +2 -1
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message/_cli.py +87 -20
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message/_gemini.py +6 -1
- git_commit_message-0.8.1/src/git_commit_message/_git.py +269 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message/_gpt.py +7 -1
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message/_llm.py +23 -5
- git_commit_message-0.8.1/src/git_commit_message/_ollama.py +122 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message.egg-info/PKG-INFO +109 -45
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message.egg-info/SOURCES.txt +1 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message.egg-info/requires.txt +1 -0
- git_commit_message-0.7.0/README.md +0 -149
- git_commit_message-0.7.0/src/git_commit_message/_git.py +0 -114
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/UNLICENSE +0 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/setup.cfg +0 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message/__init__.py +0 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message/__main__.py +0 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message.egg-info/dependency_links.txt +0 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message.egg-info/entry_points.txt +0 -0
- {git_commit_message-0.7.0 → git_commit_message-0.8.1}/src/git_commit_message.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-commit-message
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.1
|
|
4
4
|
Summary: Generate Git commit messages from staged changes using LLM
|
|
5
5
|
Maintainer-email: Mina Her <minacle@live.com>
|
|
6
6
|
License: This is free and unencumbered software released into the public domain.
|
|
@@ -45,16 +45,22 @@ Requires-Python: >=3.13
|
|
|
45
45
|
Description-Content-Type: text/markdown
|
|
46
46
|
Requires-Dist: babel>=2.17.0
|
|
47
47
|
Requires-Dist: google-genai>=1.56.0
|
|
48
|
+
Requires-Dist: ollama>=0.4.0
|
|
48
49
|
Requires-Dist: openai>=2.6.1
|
|
49
50
|
Requires-Dist: tiktoken>=0.12.0
|
|
50
51
|
|
|
51
52
|
# git-commit-message
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
Generate a commit message from your staged changes using OpenAI, Google Gemini, or Ollama.
|
|
54
55
|
|
|
55
56
|
[](https://asciinema.org/a/jk0phFqNnc5vaCiIZEYBwZOyN)
|
|
56
57
|
|
|
57
|
-
##
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- Python 3.13+
|
|
61
|
+
- A Git repo with staged changes (`git add ...`) (or use `--amend` even if nothing is staged)
|
|
62
|
+
|
|
63
|
+
## Install
|
|
58
64
|
|
|
59
65
|
Install the latest released version from PyPI:
|
|
60
66
|
|
|
@@ -78,19 +84,43 @@ Quick check:
|
|
|
78
84
|
git-commit-message --help
|
|
79
85
|
```
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
## Setup
|
|
88
|
+
|
|
89
|
+
### OpenAI
|
|
82
90
|
|
|
83
91
|
```sh
|
|
84
92
|
export OPENAI_API_KEY="sk-..."
|
|
85
93
|
```
|
|
86
94
|
|
|
87
|
-
|
|
95
|
+
### Google Gemini
|
|
88
96
|
|
|
89
97
|
```sh
|
|
90
98
|
export GOOGLE_API_KEY="..."
|
|
91
99
|
```
|
|
92
100
|
|
|
93
|
-
|
|
101
|
+
### Ollama (local models)
|
|
102
|
+
|
|
103
|
+
1. Install Ollama: https://ollama.ai
|
|
104
|
+
2. Start the server:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
ollama serve
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
3. Pull a model:
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
ollama pull mistral
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Optional: set defaults:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
export GIT_COMMIT_MESSAGE_PROVIDER=ollama
|
|
120
|
+
export OLLAMA_MODEL=mistral
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Note (fish):
|
|
94
124
|
|
|
95
125
|
```fish
|
|
96
126
|
set -x OPENAI_API_KEY "sk-..."
|
|
@@ -104,96 +134,130 @@ python -m pip install -e .
|
|
|
104
134
|
|
|
105
135
|
## Usage
|
|
106
136
|
|
|
107
|
-
|
|
137
|
+
Generate and print a commit message:
|
|
108
138
|
|
|
109
139
|
```sh
|
|
110
140
|
git add -A
|
|
111
141
|
git-commit-message "optional extra context about the change"
|
|
112
142
|
```
|
|
113
143
|
|
|
114
|
-
|
|
144
|
+
Generate a single-line subject only:
|
|
115
145
|
|
|
116
146
|
```sh
|
|
117
147
|
git-commit-message --one-line "optional context"
|
|
118
148
|
```
|
|
119
149
|
|
|
120
|
-
|
|
150
|
+
Select provider:
|
|
121
151
|
|
|
122
152
|
```sh
|
|
123
|
-
|
|
153
|
+
# OpenAI (default)
|
|
154
|
+
git-commit-message --provider openai
|
|
155
|
+
|
|
156
|
+
# Google Gemini (via google-genai)
|
|
157
|
+
git-commit-message --provider google
|
|
158
|
+
|
|
159
|
+
# Ollama
|
|
160
|
+
git-commit-message --provider ollama
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Commit immediately (optionally open editor):
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
git-commit-message --commit "refactor parser for speed"
|
|
167
|
+
git-commit-message --commit --edit "refactor parser for speed"
|
|
124
168
|
```
|
|
125
169
|
|
|
126
|
-
|
|
170
|
+
Amend the previous commit:
|
|
127
171
|
|
|
128
172
|
```sh
|
|
129
|
-
|
|
173
|
+
# print only (useful for pasting into a GUI editor)
|
|
174
|
+
git-commit-message --amend "optional context"
|
|
175
|
+
|
|
176
|
+
# amend immediately
|
|
177
|
+
git-commit-message --commit --amend "optional context"
|
|
178
|
+
|
|
179
|
+
# amend immediately, but open editor for final tweaks
|
|
180
|
+
git-commit-message --commit --amend --edit "optional context"
|
|
130
181
|
```
|
|
131
182
|
|
|
132
|
-
|
|
183
|
+
Limit subject length:
|
|
133
184
|
|
|
134
185
|
```sh
|
|
135
|
-
git-commit-message --one-line --max-length 50
|
|
186
|
+
git-commit-message --one-line --max-length 50
|
|
136
187
|
```
|
|
137
188
|
|
|
138
|
-
|
|
189
|
+
Chunk/summarise long diffs by token budget:
|
|
139
190
|
|
|
140
191
|
```sh
|
|
141
192
|
# force a single summary pass over the whole diff (default)
|
|
142
|
-
git-commit-message --chunk-tokens 0
|
|
193
|
+
git-commit-message --chunk-tokens 0
|
|
143
194
|
|
|
144
195
|
# chunk the diff into ~4000-token pieces before summarising
|
|
145
|
-
git-commit-message --chunk-tokens 4000
|
|
196
|
+
git-commit-message --chunk-tokens 4000
|
|
146
197
|
|
|
147
198
|
# disable summarisation and use the legacy one-shot prompt
|
|
148
|
-
git-commit-message --chunk-tokens -1
|
|
199
|
+
git-commit-message --chunk-tokens -1
|
|
149
200
|
```
|
|
150
201
|
|
|
151
|
-
|
|
202
|
+
Select output language/locale (IETF language tag):
|
|
152
203
|
|
|
153
204
|
```sh
|
|
154
|
-
git-commit-message --
|
|
205
|
+
git-commit-message --language en-US
|
|
206
|
+
git-commit-message --language ko-KR
|
|
207
|
+
git-commit-message --language ja-JP
|
|
155
208
|
```
|
|
156
209
|
|
|
157
|
-
|
|
210
|
+
Print debug info:
|
|
158
211
|
|
|
159
212
|
```sh
|
|
160
|
-
git-commit-message --debug
|
|
213
|
+
git-commit-message --debug
|
|
161
214
|
```
|
|
162
215
|
|
|
163
|
-
|
|
216
|
+
Configure Ollama host (if running on a different machine):
|
|
164
217
|
|
|
165
218
|
```sh
|
|
166
|
-
|
|
167
|
-
|
|
219
|
+
git-commit-message --provider ollama --host http://192.168.1.100:11434
|
|
220
|
+
```
|
|
168
221
|
|
|
169
|
-
|
|
170
|
-
git-commit-message --language ko-KR
|
|
222
|
+
## Options
|
|
171
223
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
224
|
+
- `--provider {openai,google,ollama}`: provider to use (default: `openai`)
|
|
225
|
+
- `--model MODEL`: model override (provider-specific)
|
|
226
|
+
- `--language TAG`: output language/locale (default: `en-GB`)
|
|
227
|
+
- `--one-line`: output subject only
|
|
228
|
+
- `--max-length N`: max subject length (default: 72)
|
|
229
|
+
- `--chunk-tokens N`: token budget per diff chunk (`0` = single summary pass, `-1` disables summarisation)
|
|
230
|
+
- `--debug`: print request/response details
|
|
231
|
+
- `--commit`: run `git commit -m <message>`
|
|
232
|
+
- `--amend`: generate a message suitable for amending the previous commit (diff is from the amended commit's parent to the staged index; if nothing is staged, this effectively becomes the diff introduced by `HEAD`)
|
|
233
|
+
- `--edit`: with `--commit`, open editor for final message
|
|
234
|
+
- `--host URL`: host URL for providers like Ollama (default: `http://localhost:11434`)
|
|
235
|
+
|
|
236
|
+
## Environment variables
|
|
175
237
|
|
|
176
|
-
|
|
238
|
+
Required:
|
|
177
239
|
|
|
178
|
-
-
|
|
179
|
-
-
|
|
240
|
+
- `OPENAI_API_KEY`: when provider is `openai`
|
|
241
|
+
- `GOOGLE_API_KEY`: when provider is `google`
|
|
180
242
|
|
|
181
|
-
|
|
243
|
+
Optional:
|
|
182
244
|
|
|
183
|
-
- `
|
|
184
|
-
- `
|
|
185
|
-
- `
|
|
186
|
-
- `
|
|
187
|
-
- `
|
|
188
|
-
- `GIT_COMMIT_MESSAGE_LANGUAGE`:
|
|
189
|
-
- `GIT_COMMIT_MESSAGE_CHUNK_TOKENS`:
|
|
245
|
+
- `GIT_COMMIT_MESSAGE_PROVIDER`: default provider (`openai` by default). `--provider` overrides this.
|
|
246
|
+
- `GIT_COMMIT_MESSAGE_MODEL`: model override for any provider. `--model` overrides this.
|
|
247
|
+
- `OPENAI_MODEL`: OpenAI-only model override (used if `--model`/`GIT_COMMIT_MESSAGE_MODEL` are not set)
|
|
248
|
+
- `OLLAMA_MODEL`: Ollama-only model override (used if `--model`/`GIT_COMMIT_MESSAGE_MODEL` are not set)
|
|
249
|
+
- `OLLAMA_HOST`: Ollama server URL (default: `http://localhost:11434`)
|
|
250
|
+
- `GIT_COMMIT_MESSAGE_LANGUAGE`: default language/locale (default: `en-GB`)
|
|
251
|
+
- `GIT_COMMIT_MESSAGE_CHUNK_TOKENS`: default chunk token budget (default: `0`)
|
|
190
252
|
|
|
191
|
-
|
|
253
|
+
Default models (if not overridden):
|
|
192
254
|
|
|
193
|
-
-
|
|
255
|
+
- OpenAI: `gpt-5-mini`
|
|
256
|
+
- Google: `gemini-2.5-flash`
|
|
257
|
+
- Ollama: `gpt-oss:20b`
|
|
194
258
|
|
|
195
|
-
## AI
|
|
259
|
+
## AI-generated code notice
|
|
196
260
|
|
|
197
261
|
Parts of this project were created with assistance from AI tools (e.g. large language models).
|
|
198
|
-
All AI
|
|
262
|
+
All AI-assisted contributions were reviewed and adapted by maintainers before inclusion.
|
|
199
263
|
If you need provenance for specific changes, please refer to the Git history and commit messages.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# git-commit-message
|
|
2
|
+
|
|
3
|
+
Generate a commit message from your staged changes using OpenAI, Google Gemini, or Ollama.
|
|
4
|
+
|
|
5
|
+
[](https://asciinema.org/a/jk0phFqNnc5vaCiIZEYBwZOyN)
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Python 3.13+
|
|
10
|
+
- A Git repo with staged changes (`git add ...`) (or use `--amend` even if nothing is staged)
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
Install the latest released version from PyPI:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
# User environment (recommended)
|
|
18
|
+
python -m pip install --user git-commit-message
|
|
19
|
+
|
|
20
|
+
# Or system/virtualenv as appropriate
|
|
21
|
+
python -m pip install git-commit-message
|
|
22
|
+
|
|
23
|
+
# Or with pipx for isolated CLI installs
|
|
24
|
+
pipx install git-commit-message
|
|
25
|
+
|
|
26
|
+
# Upgrade to the newest version
|
|
27
|
+
python -m pip install --upgrade git-commit-message
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Quick check:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
git-commit-message --help
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Setup
|
|
37
|
+
|
|
38
|
+
### OpenAI
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
export OPENAI_API_KEY="sk-..."
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Google Gemini
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
export GOOGLE_API_KEY="..."
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Ollama (local models)
|
|
51
|
+
|
|
52
|
+
1. Install Ollama: https://ollama.ai
|
|
53
|
+
2. Start the server:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
ollama serve
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
3. Pull a model:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
ollama pull mistral
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Optional: set defaults:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
export GIT_COMMIT_MESSAGE_PROVIDER=ollama
|
|
69
|
+
export OLLAMA_MODEL=mistral
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Note (fish):
|
|
73
|
+
|
|
74
|
+
```fish
|
|
75
|
+
set -x OPENAI_API_KEY "sk-..."
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Install (editable)
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
python -m pip install -e .
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
Generate and print a commit message:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
git add -A
|
|
90
|
+
git-commit-message "optional extra context about the change"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Generate a single-line subject only:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
git-commit-message --one-line "optional context"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Select provider:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
# OpenAI (default)
|
|
103
|
+
git-commit-message --provider openai
|
|
104
|
+
|
|
105
|
+
# Google Gemini (via google-genai)
|
|
106
|
+
git-commit-message --provider google
|
|
107
|
+
|
|
108
|
+
# Ollama
|
|
109
|
+
git-commit-message --provider ollama
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Commit immediately (optionally open editor):
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
git-commit-message --commit "refactor parser for speed"
|
|
116
|
+
git-commit-message --commit --edit "refactor parser for speed"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Amend the previous commit:
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
# print only (useful for pasting into a GUI editor)
|
|
123
|
+
git-commit-message --amend "optional context"
|
|
124
|
+
|
|
125
|
+
# amend immediately
|
|
126
|
+
git-commit-message --commit --amend "optional context"
|
|
127
|
+
|
|
128
|
+
# amend immediately, but open editor for final tweaks
|
|
129
|
+
git-commit-message --commit --amend --edit "optional context"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Limit subject length:
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
git-commit-message --one-line --max-length 50
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Chunk/summarise long diffs by token budget:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
# force a single summary pass over the whole diff (default)
|
|
142
|
+
git-commit-message --chunk-tokens 0
|
|
143
|
+
|
|
144
|
+
# chunk the diff into ~4000-token pieces before summarising
|
|
145
|
+
git-commit-message --chunk-tokens 4000
|
|
146
|
+
|
|
147
|
+
# disable summarisation and use the legacy one-shot prompt
|
|
148
|
+
git-commit-message --chunk-tokens -1
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Select output language/locale (IETF language tag):
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
git-commit-message --language en-US
|
|
155
|
+
git-commit-message --language ko-KR
|
|
156
|
+
git-commit-message --language ja-JP
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Print debug info:
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
git-commit-message --debug
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Configure Ollama host (if running on a different machine):
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
git-commit-message --provider ollama --host http://192.168.1.100:11434
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Options
|
|
172
|
+
|
|
173
|
+
- `--provider {openai,google,ollama}`: provider to use (default: `openai`)
|
|
174
|
+
- `--model MODEL`: model override (provider-specific)
|
|
175
|
+
- `--language TAG`: output language/locale (default: `en-GB`)
|
|
176
|
+
- `--one-line`: output subject only
|
|
177
|
+
- `--max-length N`: max subject length (default: 72)
|
|
178
|
+
- `--chunk-tokens N`: token budget per diff chunk (`0` = single summary pass, `-1` disables summarisation)
|
|
179
|
+
- `--debug`: print request/response details
|
|
180
|
+
- `--commit`: run `git commit -m <message>`
|
|
181
|
+
- `--amend`: generate a message suitable for amending the previous commit (diff is from the amended commit's parent to the staged index; if nothing is staged, this effectively becomes the diff introduced by `HEAD`)
|
|
182
|
+
- `--edit`: with `--commit`, open editor for final message
|
|
183
|
+
- `--host URL`: host URL for providers like Ollama (default: `http://localhost:11434`)
|
|
184
|
+
|
|
185
|
+
## Environment variables
|
|
186
|
+
|
|
187
|
+
Required:
|
|
188
|
+
|
|
189
|
+
- `OPENAI_API_KEY`: when provider is `openai`
|
|
190
|
+
- `GOOGLE_API_KEY`: when provider is `google`
|
|
191
|
+
|
|
192
|
+
Optional:
|
|
193
|
+
|
|
194
|
+
- `GIT_COMMIT_MESSAGE_PROVIDER`: default provider (`openai` by default). `--provider` overrides this.
|
|
195
|
+
- `GIT_COMMIT_MESSAGE_MODEL`: model override for any provider. `--model` overrides this.
|
|
196
|
+
- `OPENAI_MODEL`: OpenAI-only model override (used if `--model`/`GIT_COMMIT_MESSAGE_MODEL` are not set)
|
|
197
|
+
- `OLLAMA_MODEL`: Ollama-only model override (used if `--model`/`GIT_COMMIT_MESSAGE_MODEL` are not set)
|
|
198
|
+
- `OLLAMA_HOST`: Ollama server URL (default: `http://localhost:11434`)
|
|
199
|
+
- `GIT_COMMIT_MESSAGE_LANGUAGE`: default language/locale (default: `en-GB`)
|
|
200
|
+
- `GIT_COMMIT_MESSAGE_CHUNK_TOKENS`: default chunk token budget (default: `0`)
|
|
201
|
+
|
|
202
|
+
Default models (if not overridden):
|
|
203
|
+
|
|
204
|
+
- OpenAI: `gpt-5-mini`
|
|
205
|
+
- Google: `gemini-2.5-flash`
|
|
206
|
+
- Ollama: `gpt-oss:20b`
|
|
207
|
+
|
|
208
|
+
## AI-generated code notice
|
|
209
|
+
|
|
210
|
+
Parts of this project were created with assistance from AI tools (e.g. large language models).
|
|
211
|
+
All AI-assisted contributions were reviewed and adapted by maintainers before inclusion.
|
|
212
|
+
If you need provenance for specific changes, please refer to the Git history and commit messages.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "git-commit-message"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.8.1"
|
|
4
4
|
description = "Generate Git commit messages from staged changes using LLM"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
7
7
|
dependencies = [
|
|
8
8
|
"babel>=2.17.0",
|
|
9
9
|
"google-genai>=1.56.0",
|
|
10
|
+
"ollama>=0.4.0",
|
|
10
11
|
"openai>=2.6.1",
|
|
11
12
|
"tiktoken>=0.12.0",
|
|
12
13
|
]
|
|
@@ -17,7 +17,9 @@ from ._git import (
|
|
|
17
17
|
commit_with_message,
|
|
18
18
|
get_repo_root,
|
|
19
19
|
get_staged_diff,
|
|
20
|
+
has_head_commit,
|
|
20
21
|
has_staged_changes,
|
|
22
|
+
resolve_amend_base_ref,
|
|
21
23
|
)
|
|
22
24
|
from ._llm import (
|
|
23
25
|
CommitMessageResult,
|
|
@@ -27,6 +29,40 @@ from ._llm import (
|
|
|
27
29
|
)
|
|
28
30
|
|
|
29
31
|
|
|
32
|
+
class CliArgs(Namespace):
|
|
33
|
+
__slots__ = (
|
|
34
|
+
"description",
|
|
35
|
+
"commit",
|
|
36
|
+
"amend",
|
|
37
|
+
"edit",
|
|
38
|
+
"provider",
|
|
39
|
+
"model",
|
|
40
|
+
"language",
|
|
41
|
+
"debug",
|
|
42
|
+
"one_line",
|
|
43
|
+
"max_length",
|
|
44
|
+
"chunk_tokens",
|
|
45
|
+
"host",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
/,
|
|
51
|
+
) -> None:
|
|
52
|
+
self.description: str | None = None
|
|
53
|
+
self.commit: bool = False
|
|
54
|
+
self.amend: bool = False
|
|
55
|
+
self.edit: bool = False
|
|
56
|
+
self.provider: str | None = None
|
|
57
|
+
self.model: str | None = None
|
|
58
|
+
self.language: str | None = None
|
|
59
|
+
self.debug: bool = False
|
|
60
|
+
self.one_line: bool = False
|
|
61
|
+
self.max_length: int | None = None
|
|
62
|
+
self.chunk_tokens: int | None = None
|
|
63
|
+
self.host: str | None = None
|
|
64
|
+
|
|
65
|
+
|
|
30
66
|
def _env_chunk_tokens_default() -> int | None:
|
|
31
67
|
"""Return chunk token default from env if valid, else None."""
|
|
32
68
|
|
|
@@ -67,6 +103,16 @@ def _build_parser() -> ArgumentParser:
|
|
|
67
103
|
help="Commit immediately with the generated message.",
|
|
68
104
|
)
|
|
69
105
|
|
|
106
|
+
parser.add_argument(
|
|
107
|
+
"--amend",
|
|
108
|
+
action="store_true",
|
|
109
|
+
help=(
|
|
110
|
+
"Generate a message suitable for amending the previous commit. "
|
|
111
|
+
"When set, the diff is computed from the amended commit's parent to the staged index. "
|
|
112
|
+
"Use with '--commit' to run the amend, or omit '--commit' to print the message only."
|
|
113
|
+
),
|
|
114
|
+
)
|
|
115
|
+
|
|
70
116
|
parser.add_argument(
|
|
71
117
|
"--edit",
|
|
72
118
|
action="store_true",
|
|
@@ -87,7 +133,7 @@ def _build_parser() -> ArgumentParser:
|
|
|
87
133
|
"--model",
|
|
88
134
|
default=None,
|
|
89
135
|
help=(
|
|
90
|
-
"Model name to use. If unspecified, uses GIT_COMMIT_MESSAGE_MODEL or a provider-specific default (openai: gpt-5-mini; google: gemini-2.5-flash)."
|
|
136
|
+
"Model name to use. If unspecified, uses GIT_COMMIT_MESSAGE_MODEL or a provider-specific default (openai: gpt-5-mini; google: gemini-2.5-flash; ollama: gpt-oss:20b)."
|
|
91
137
|
),
|
|
92
138
|
)
|
|
93
139
|
|
|
@@ -134,11 +180,21 @@ def _build_parser() -> ArgumentParser:
|
|
|
134
180
|
),
|
|
135
181
|
)
|
|
136
182
|
|
|
183
|
+
parser.add_argument(
|
|
184
|
+
"--host",
|
|
185
|
+
dest="host",
|
|
186
|
+
default=None,
|
|
187
|
+
help=(
|
|
188
|
+
"Host URL for API providers like Ollama (default: http://localhost:11434). "
|
|
189
|
+
"You may also set OLLAMA_HOST for Ollama."
|
|
190
|
+
),
|
|
191
|
+
)
|
|
192
|
+
|
|
137
193
|
return parser
|
|
138
194
|
|
|
139
195
|
|
|
140
196
|
def _run(
|
|
141
|
-
args:
|
|
197
|
+
args: CliArgs,
|
|
142
198
|
/,
|
|
143
199
|
) -> int:
|
|
144
200
|
"""Main execution logic.
|
|
@@ -156,11 +212,19 @@ def _run(
|
|
|
156
212
|
|
|
157
213
|
repo_root: Path = get_repo_root()
|
|
158
214
|
|
|
159
|
-
if
|
|
160
|
-
|
|
161
|
-
|
|
215
|
+
if args.amend:
|
|
216
|
+
if not has_head_commit(repo_root):
|
|
217
|
+
print("Cannot amend: the repository has no commits yet.", file=stderr)
|
|
218
|
+
return 2
|
|
219
|
+
|
|
220
|
+
base_ref = resolve_amend_base_ref(repo_root)
|
|
221
|
+
diff_text: str = get_staged_diff(repo_root, base_ref=base_ref)
|
|
222
|
+
else:
|
|
223
|
+
if not has_staged_changes(repo_root):
|
|
224
|
+
print("No staged changes. Run 'git add' and try again.", file=stderr)
|
|
225
|
+
return 2
|
|
162
226
|
|
|
163
|
-
|
|
227
|
+
diff_text = get_staged_diff(repo_root)
|
|
164
228
|
|
|
165
229
|
hint: str | None = args.description if isinstance(args.description, str) else None
|
|
166
230
|
|
|
@@ -177,11 +241,12 @@ def _run(
|
|
|
177
241
|
diff_text,
|
|
178
242
|
hint,
|
|
179
243
|
args.model,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
244
|
+
args.one_line,
|
|
245
|
+
args.max_length,
|
|
246
|
+
args.language,
|
|
183
247
|
chunk_tokens,
|
|
184
|
-
|
|
248
|
+
args.provider,
|
|
249
|
+
args.host,
|
|
185
250
|
)
|
|
186
251
|
message = result.message
|
|
187
252
|
else:
|
|
@@ -189,11 +254,12 @@ def _run(
|
|
|
189
254
|
diff_text,
|
|
190
255
|
hint,
|
|
191
256
|
args.model,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
257
|
+
args.one_line,
|
|
258
|
+
args.max_length,
|
|
259
|
+
args.language,
|
|
195
260
|
chunk_tokens,
|
|
196
|
-
|
|
261
|
+
args.provider,
|
|
262
|
+
args.host,
|
|
197
263
|
)
|
|
198
264
|
except UnsupportedProviderError as exc:
|
|
199
265
|
print(str(exc), file=stderr)
|
|
@@ -203,7 +269,7 @@ def _run(
|
|
|
203
269
|
return 3
|
|
204
270
|
|
|
205
271
|
# Option: force single-line message
|
|
206
|
-
if
|
|
272
|
+
if args.one_line:
|
|
207
273
|
# Use the first non-empty line only
|
|
208
274
|
for line in (ln.strip() for ln in message.splitlines()):
|
|
209
275
|
if line:
|
|
@@ -218,7 +284,7 @@ def _run(
|
|
|
218
284
|
print(f"==== {result.provider} Usage ====")
|
|
219
285
|
print(f"provider: {result.provider}")
|
|
220
286
|
print(f"model: {result.model}")
|
|
221
|
-
print(f"response_id: {
|
|
287
|
+
print(f"response_id: {result.response_id or '(n/a)'}")
|
|
222
288
|
if result.total_tokens is not None:
|
|
223
289
|
print(
|
|
224
290
|
f"tokens: prompt={result.prompt_tokens} completion={result.completion_tokens} total={result.total_tokens}"
|
|
@@ -240,7 +306,7 @@ def _run(
|
|
|
240
306
|
print(f"==== {result.provider} Usage ====")
|
|
241
307
|
print(f"provider: {result.provider}")
|
|
242
308
|
print(f"model: {result.model}")
|
|
243
|
-
print(f"response_id: {
|
|
309
|
+
print(f"response_id: {result.response_id or '(n/a)'}")
|
|
244
310
|
if result.total_tokens is not None:
|
|
245
311
|
print(
|
|
246
312
|
f"tokens: prompt={result.prompt_tokens} completion={result.completion_tokens} total={result.total_tokens}"
|
|
@@ -255,9 +321,9 @@ def _run(
|
|
|
255
321
|
print(message)
|
|
256
322
|
|
|
257
323
|
if args.edit:
|
|
258
|
-
rc: int = commit_with_message(message, True, repo_root)
|
|
324
|
+
rc: int = commit_with_message(message, True, repo_root, amend=args.amend)
|
|
259
325
|
else:
|
|
260
|
-
rc = commit_with_message(message, False, repo_root)
|
|
326
|
+
rc = commit_with_message(message, False, repo_root, amend=args.amend)
|
|
261
327
|
|
|
262
328
|
return rc
|
|
263
329
|
|
|
@@ -269,7 +335,8 @@ def main() -> None:
|
|
|
269
335
|
"""
|
|
270
336
|
|
|
271
337
|
parser: Final[ArgumentParser] = _build_parser()
|
|
272
|
-
args
|
|
338
|
+
args = CliArgs()
|
|
339
|
+
parser.parse_args(namespace=args)
|
|
273
340
|
|
|
274
341
|
if args.edit and not args.commit:
|
|
275
342
|
print("'--edit' must be used together with '--commit'.", file=stderr)
|