git-copilot-commit 0.1.1__tar.gz → 0.1.3__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_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/PKG-INFO +61 -7
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/README.md +60 -6
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/pyproject.toml +1 -1
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/src/git_copilot_commit/cli.py +48 -9
- git_copilot_commit-0.1.3/src/git_copilot_commit/settings.py +89 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/uv.lock +1 -1
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/.gitignore +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/.python-version +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/LICENSE +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/src/git_copilot_commit/__init__.py +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/src/git_copilot_commit/git.py +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.3}/src/git_copilot_commit/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-copilot-commit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Automatically generate and commit changes using copilot
|
|
5
5
|
Author-email: Dheepak Krishnamurthy <1813121+kdheepak@users.noreply.github.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -20,6 +20,8 @@ GitHub Copilot.
|
|
|
20
20
|
|
|
21
21
|
- **AI-Generated Commit Messages**: Uses GitHub Copilot to analyze your staged changes and generate
|
|
22
22
|
conventional commit messages
|
|
23
|
+
- **Multiple AI Models**: Choose from GPT-4, Claude, Gemini, and other available models
|
|
24
|
+
- **Configurable Defaults**: Set a default model to use across all commits
|
|
23
25
|
- **Message Editing**: Edit generated messages using your git-configured editor or commit directly
|
|
24
26
|
- **Conventional Commits**: Follows the [Conventional Commits](https://www.conventionalcommits.org/)
|
|
25
27
|
specification
|
|
@@ -43,8 +45,7 @@ pipx install git-copilot-commit
|
|
|
43
45
|
|
|
44
46
|
## Prerequisites
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
2. **Authentication**: Authenticate with GitHub Copilot before first use
|
|
48
|
+
**GitHub Copilot Access**: You need an active GitHub Copilot subscription
|
|
48
49
|
|
|
49
50
|
## Quick Start
|
|
50
51
|
|
|
@@ -64,7 +65,7 @@ pipx install git-copilot-commit
|
|
|
64
65
|
|
|
65
66
|
## Usage
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
### `commit`
|
|
68
69
|
|
|
69
70
|
Automatically commit changes in the current git repository:
|
|
70
71
|
|
|
@@ -76,6 +77,7 @@ git-copilot-commit commit
|
|
|
76
77
|
|
|
77
78
|
- `--all, -a`: Stage all files before committing
|
|
78
79
|
- `--verbose, -v`: Show verbose output with file details
|
|
80
|
+
- `--model, -m`: Specify which AI model to use for generating the commit message
|
|
79
81
|
|
|
80
82
|
1. The tool analyzes your changes
|
|
81
83
|
2. Prompts you to stage files (if needed)
|
|
@@ -85,7 +87,7 @@ git-copilot-commit commit
|
|
|
85
87
|
- `(e)dit`: Edit the message in your git-configured editor
|
|
86
88
|
- `(q)uit`: Cancel the commit
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
### `authenticate`
|
|
89
91
|
|
|
90
92
|
Set up authentication with GitHub Copilot:
|
|
91
93
|
|
|
@@ -93,7 +95,7 @@ Set up authentication with GitHub Copilot:
|
|
|
93
95
|
git-copilot-commit authenticate
|
|
94
96
|
```
|
|
95
97
|
|
|
96
|
-
|
|
98
|
+
### `models`
|
|
97
99
|
|
|
98
100
|
List available AI models:
|
|
99
101
|
|
|
@@ -101,7 +103,19 @@ List available AI models:
|
|
|
101
103
|
git-copilot-commit models
|
|
102
104
|
```
|
|
103
105
|
|
|
104
|
-
###
|
|
106
|
+
### `config`
|
|
107
|
+
|
|
108
|
+
Manage application configuration:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Show current configuration
|
|
112
|
+
git-copilot-commit config --show
|
|
113
|
+
|
|
114
|
+
# Set a default model for all commits
|
|
115
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Examples
|
|
105
119
|
|
|
106
120
|
**Commit all changes with staging prompts:**
|
|
107
121
|
|
|
@@ -115,6 +129,25 @@ git-copilot-commit commit --all
|
|
|
115
129
|
git-copilot-commit commit --verbose
|
|
116
130
|
```
|
|
117
131
|
|
|
132
|
+
**Use a specific AI model:**
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Set up a default model and use it:**
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Set default model once
|
|
142
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
143
|
+
|
|
144
|
+
# Now all commits will use gpt-4o by default
|
|
145
|
+
git-copilot-commit commit
|
|
146
|
+
|
|
147
|
+
# Override with a different model when needed
|
|
148
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
149
|
+
```
|
|
150
|
+
|
|
118
151
|
## Generated Commit Message Format
|
|
119
152
|
|
|
120
153
|
The tool follows the [Conventional Commits](https://www.conventionalcommits.org/) specification:
|
|
@@ -141,3 +174,24 @@ The tool follows the [Conventional Commits](https://www.conventionalcommits.org/
|
|
|
141
174
|
- `fix(database): handle connection retries properly`
|
|
142
175
|
- `docs(readme): update installation instructions`
|
|
143
176
|
- `refactor(utils): simplify date parsing logic`
|
|
177
|
+
|
|
178
|
+
## Git Configuration
|
|
179
|
+
|
|
180
|
+
For the best experience with git-copilot-commit, consider adding this alias for the commit command:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Add a git alias for quick access
|
|
184
|
+
git config --global alias.ai-commit "!git-copilot-commit commit"
|
|
185
|
+
|
|
186
|
+
# Now you can use:
|
|
187
|
+
git ai-commit
|
|
188
|
+
git ai-commit --model claude-3.5-sonnet
|
|
189
|
+
git ai-commit --all --verbose
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
You can also configure git to show more context in diffs, which can help when reviewing changes:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Show more context in diffs
|
|
196
|
+
git config --global diff.context 3
|
|
197
|
+
```
|
|
@@ -7,6 +7,8 @@ GitHub Copilot.
|
|
|
7
7
|
|
|
8
8
|
- **AI-Generated Commit Messages**: Uses GitHub Copilot to analyze your staged changes and generate
|
|
9
9
|
conventional commit messages
|
|
10
|
+
- **Multiple AI Models**: Choose from GPT-4, Claude, Gemini, and other available models
|
|
11
|
+
- **Configurable Defaults**: Set a default model to use across all commits
|
|
10
12
|
- **Message Editing**: Edit generated messages using your git-configured editor or commit directly
|
|
11
13
|
- **Conventional Commits**: Follows the [Conventional Commits](https://www.conventionalcommits.org/)
|
|
12
14
|
specification
|
|
@@ -30,8 +32,7 @@ pipx install git-copilot-commit
|
|
|
30
32
|
|
|
31
33
|
## Prerequisites
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
2. **Authentication**: Authenticate with GitHub Copilot before first use
|
|
35
|
+
**GitHub Copilot Access**: You need an active GitHub Copilot subscription
|
|
35
36
|
|
|
36
37
|
## Quick Start
|
|
37
38
|
|
|
@@ -51,7 +52,7 @@ pipx install git-copilot-commit
|
|
|
51
52
|
|
|
52
53
|
## Usage
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
### `commit`
|
|
55
56
|
|
|
56
57
|
Automatically commit changes in the current git repository:
|
|
57
58
|
|
|
@@ -63,6 +64,7 @@ git-copilot-commit commit
|
|
|
63
64
|
|
|
64
65
|
- `--all, -a`: Stage all files before committing
|
|
65
66
|
- `--verbose, -v`: Show verbose output with file details
|
|
67
|
+
- `--model, -m`: Specify which AI model to use for generating the commit message
|
|
66
68
|
|
|
67
69
|
1. The tool analyzes your changes
|
|
68
70
|
2. Prompts you to stage files (if needed)
|
|
@@ -72,7 +74,7 @@ git-copilot-commit commit
|
|
|
72
74
|
- `(e)dit`: Edit the message in your git-configured editor
|
|
73
75
|
- `(q)uit`: Cancel the commit
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
### `authenticate`
|
|
76
78
|
|
|
77
79
|
Set up authentication with GitHub Copilot:
|
|
78
80
|
|
|
@@ -80,7 +82,7 @@ Set up authentication with GitHub Copilot:
|
|
|
80
82
|
git-copilot-commit authenticate
|
|
81
83
|
```
|
|
82
84
|
|
|
83
|
-
|
|
85
|
+
### `models`
|
|
84
86
|
|
|
85
87
|
List available AI models:
|
|
86
88
|
|
|
@@ -88,7 +90,19 @@ List available AI models:
|
|
|
88
90
|
git-copilot-commit models
|
|
89
91
|
```
|
|
90
92
|
|
|
91
|
-
###
|
|
93
|
+
### `config`
|
|
94
|
+
|
|
95
|
+
Manage application configuration:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Show current configuration
|
|
99
|
+
git-copilot-commit config --show
|
|
100
|
+
|
|
101
|
+
# Set a default model for all commits
|
|
102
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Examples
|
|
92
106
|
|
|
93
107
|
**Commit all changes with staging prompts:**
|
|
94
108
|
|
|
@@ -102,6 +116,25 @@ git-copilot-commit commit --all
|
|
|
102
116
|
git-copilot-commit commit --verbose
|
|
103
117
|
```
|
|
104
118
|
|
|
119
|
+
**Use a specific AI model:**
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Set up a default model and use it:**
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Set default model once
|
|
129
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
130
|
+
|
|
131
|
+
# Now all commits will use gpt-4o by default
|
|
132
|
+
git-copilot-commit commit
|
|
133
|
+
|
|
134
|
+
# Override with a different model when needed
|
|
135
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
136
|
+
```
|
|
137
|
+
|
|
105
138
|
## Generated Commit Message Format
|
|
106
139
|
|
|
107
140
|
The tool follows the [Conventional Commits](https://www.conventionalcommits.org/) specification:
|
|
@@ -128,3 +161,24 @@ The tool follows the [Conventional Commits](https://www.conventionalcommits.org/
|
|
|
128
161
|
- `fix(database): handle connection retries properly`
|
|
129
162
|
- `docs(readme): update installation instructions`
|
|
130
163
|
- `refactor(utils): simplify date parsing logic`
|
|
164
|
+
|
|
165
|
+
## Git Configuration
|
|
166
|
+
|
|
167
|
+
For the best experience with git-copilot-commit, consider adding this alias for the commit command:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Add a git alias for quick access
|
|
171
|
+
git config --global alias.ai-commit "!git-copilot-commit commit"
|
|
172
|
+
|
|
173
|
+
# Now you can use:
|
|
174
|
+
git ai-commit
|
|
175
|
+
git ai-commit --model claude-3.5-sonnet
|
|
176
|
+
git ai-commit --all --verbose
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
You can also configure git to show more context in diffs, which can help when reviewing changes:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Show more context in diffs
|
|
183
|
+
git config --global diff.context 3
|
|
184
|
+
```
|
|
@@ -11,6 +11,7 @@ from rich.table import Table
|
|
|
11
11
|
from pycopilot.copilot import Copilot
|
|
12
12
|
from pycopilot.auth import Authentication
|
|
13
13
|
from .git import GitRepository, GitError, NotAGitRepositoryError, GitStatus
|
|
14
|
+
from .settings import Settings
|
|
14
15
|
|
|
15
16
|
console = Console()
|
|
16
17
|
app = typer.Typer(help=__doc__, add_completion=False)
|
|
@@ -59,7 +60,9 @@ def display_file_status(status: GitStatus) -> None:
|
|
|
59
60
|
console.print(table)
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
def generate_commit_message(
|
|
63
|
+
def generate_commit_message(
|
|
64
|
+
repo: GitRepository, status: GitStatus, model: str | None = None
|
|
65
|
+
) -> str:
|
|
63
66
|
"""Generate a conventional commit message using Copilot API."""
|
|
64
67
|
|
|
65
68
|
# Get recent commits for context
|
|
@@ -179,7 +182,9 @@ def commit(
|
|
|
179
182
|
False, "--all", "-a", help="Stage all files before committing"
|
|
180
183
|
),
|
|
181
184
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show verbose output"),
|
|
182
|
-
model: str = typer.Option(
|
|
185
|
+
model: str | None = typer.Option(
|
|
186
|
+
None, "--model", "-m", help="Model to use for generating commit message"
|
|
187
|
+
),
|
|
183
188
|
):
|
|
184
189
|
"""
|
|
185
190
|
Automatically commit changes in the current git repository.
|
|
@@ -190,6 +195,11 @@ def commit(
|
|
|
190
195
|
console.print("[red]Error: Not in a git repository[/red]")
|
|
191
196
|
raise typer.Exit(1)
|
|
192
197
|
|
|
198
|
+
# Load settings and use default model if none provided
|
|
199
|
+
settings = Settings()
|
|
200
|
+
if model is None:
|
|
201
|
+
model = settings.default_model
|
|
202
|
+
|
|
193
203
|
# Get initial status
|
|
194
204
|
status = repo.get_status()
|
|
195
205
|
|
|
@@ -206,19 +216,23 @@ def commit(
|
|
|
206
216
|
repo.stage_files() # Stage all files
|
|
207
217
|
console.print("[green]Staged all files.[/green]")
|
|
208
218
|
else:
|
|
209
|
-
#
|
|
219
|
+
# Show git status once if there are unstaged or untracked files to prompt about
|
|
220
|
+
if status.has_unstaged_changes or status.has_untracked_files:
|
|
221
|
+
git_status_output = repo._run_git_command(["status"])
|
|
222
|
+
console.print(git_status_output.stdout)
|
|
223
|
+
|
|
210
224
|
if status.has_unstaged_changes:
|
|
211
|
-
if Confirm.ask(
|
|
225
|
+
if Confirm.ask(
|
|
226
|
+
"Modified files found. Add [bold yellow]all unstaged changes[/] to staging?"
|
|
227
|
+
):
|
|
212
228
|
repo.stage_modified()
|
|
213
229
|
console.print("[green]Staged modified files.[/green]")
|
|
214
|
-
else:
|
|
215
|
-
raise typer.Exit()
|
|
216
230
|
if status.has_untracked_files:
|
|
217
|
-
if Confirm.ask(
|
|
231
|
+
if Confirm.ask(
|
|
232
|
+
"Untracked files found. Add [bold yellow]all untracked files and unstaged changes[/] to staging?"
|
|
233
|
+
):
|
|
218
234
|
repo.stage_files()
|
|
219
235
|
console.print("[green]Staged untracked files.[/green]")
|
|
220
|
-
else:
|
|
221
|
-
raise typer.Exit()
|
|
222
236
|
|
|
223
237
|
# Refresh status after staging
|
|
224
238
|
status = repo.get_status()
|
|
@@ -315,5 +329,30 @@ def models():
|
|
|
315
329
|
console.print(table)
|
|
316
330
|
|
|
317
331
|
|
|
332
|
+
@app.command()
|
|
333
|
+
def config(
|
|
334
|
+
set_default_model: str | None = typer.Option(
|
|
335
|
+
None, "--set-default-model", help="Set default model for commit messages"
|
|
336
|
+
),
|
|
337
|
+
show: bool = typer.Option(False, "--show", help="Show current configuration"),
|
|
338
|
+
):
|
|
339
|
+
"""Manage application configuration."""
|
|
340
|
+
settings = Settings()
|
|
341
|
+
|
|
342
|
+
if set_default_model:
|
|
343
|
+
settings.default_model = set_default_model
|
|
344
|
+
console.print(f"[green]✓ Default model set to: {set_default_model}[/green]")
|
|
345
|
+
|
|
346
|
+
if show or (not set_default_model):
|
|
347
|
+
console.print("\n[bold]Current Configuration:[/bold]")
|
|
348
|
+
default_model = settings.default_model
|
|
349
|
+
if default_model:
|
|
350
|
+
console.print(f"Default model: [cyan]{default_model}[/cyan]")
|
|
351
|
+
else:
|
|
352
|
+
console.print("Default model: [dim]not set[/dim]")
|
|
353
|
+
|
|
354
|
+
console.print(f"Config file: [dim]{settings.config_file}[/dim]")
|
|
355
|
+
|
|
356
|
+
|
|
318
357
|
if __name__ == "__main__":
|
|
319
358
|
app()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Settings management using XDG Base Directory specification.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from xdg_base_dirs import (
|
|
9
|
+
xdg_cache_home,
|
|
10
|
+
xdg_config_home,
|
|
11
|
+
xdg_data_home,
|
|
12
|
+
xdg_state_home,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Settings:
|
|
17
|
+
"""Manages application settings using XDG Base Directory specification."""
|
|
18
|
+
|
|
19
|
+
APP_NAME = "git-copilot-commit"
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.config_dir = xdg_config_home() / self.APP_NAME
|
|
23
|
+
self.data_dir = xdg_data_home() / self.APP_NAME
|
|
24
|
+
self.cache_dir = xdg_cache_home() / self.APP_NAME
|
|
25
|
+
self.state_dir = xdg_state_home() / self.APP_NAME
|
|
26
|
+
|
|
27
|
+
self.config_file = self.config_dir / "config.json"
|
|
28
|
+
|
|
29
|
+
# Ensure directories exist
|
|
30
|
+
self.config_dir.mkdir(parents=True, exist_ok=True)
|
|
31
|
+
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
33
|
+
self.state_dir.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
|
|
35
|
+
self._config: dict[str, Any] = self._load_config()
|
|
36
|
+
|
|
37
|
+
def _load_config(self) -> dict[str, Any]:
|
|
38
|
+
"""Load configuration from file."""
|
|
39
|
+
if not self.config_file.exists():
|
|
40
|
+
return {}
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
with open(self.config_file, "r") as f:
|
|
44
|
+
return json.load(f)
|
|
45
|
+
except (json.JSONDecodeError, IOError):
|
|
46
|
+
return {}
|
|
47
|
+
|
|
48
|
+
def _save_config(self) -> None:
|
|
49
|
+
"""Save configuration to file."""
|
|
50
|
+
try:
|
|
51
|
+
with open(self.config_file, "w") as f:
|
|
52
|
+
json.dump(self._config, f, indent=2)
|
|
53
|
+
except IOError:
|
|
54
|
+
pass # Silently fail if we can't write
|
|
55
|
+
|
|
56
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
57
|
+
"""Get a configuration value."""
|
|
58
|
+
return self._config.get(key, default)
|
|
59
|
+
|
|
60
|
+
def set(self, key: str, value: Any) -> None:
|
|
61
|
+
"""Set a configuration value."""
|
|
62
|
+
self._config[key] = value
|
|
63
|
+
self._save_config()
|
|
64
|
+
|
|
65
|
+
def delete(self, key: str) -> None:
|
|
66
|
+
"""Delete a configuration value."""
|
|
67
|
+
if key in self._config:
|
|
68
|
+
del self._config[key]
|
|
69
|
+
self._save_config()
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def default_model(self) -> str | None:
|
|
73
|
+
"""Get the default model."""
|
|
74
|
+
return self.get("default_model")
|
|
75
|
+
|
|
76
|
+
@default_model.setter
|
|
77
|
+
def default_model(self, model: str) -> None:
|
|
78
|
+
"""Set the default model."""
|
|
79
|
+
self.set("default_model", model)
|
|
80
|
+
|
|
81
|
+
def clear_cache(self) -> None:
|
|
82
|
+
"""Clear the cache directory."""
|
|
83
|
+
for file in self.cache_dir.glob("*"):
|
|
84
|
+
if file.is_file():
|
|
85
|
+
file.unlink()
|
|
86
|
+
elif file.is_dir():
|
|
87
|
+
import shutil
|
|
88
|
+
|
|
89
|
+
shutil.rmtree(file)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|