git-copilot-commit 0.1.20__tar.gz → 0.2.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.
Files changed (18) hide show
  1. git_copilot_commit-0.2.1/.justfile +56 -0
  2. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/PKG-INFO +1 -1
  3. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/src/git_copilot_commit/cli.py +57 -32
  4. git_copilot_commit-0.2.1/src/git_copilot_commit/prompts/commit-message-generator-prompt.md +62 -0
  5. git_copilot_commit-0.1.20/src/git_copilot_commit/prompts/commit-message-generator-prompt.md +0 -70
  6. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/.github/workflows/ci.yml +0 -0
  7. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/.gitignore +0 -0
  8. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/.python-version +0 -0
  9. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/LICENSE +0 -0
  10. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/README.md +0 -0
  11. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/pyproject.toml +0 -0
  12. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/src/git_copilot_commit/__init__.py +0 -0
  13. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/src/git_copilot_commit/git.py +0 -0
  14. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/src/git_copilot_commit/py.typed +0 -0
  15. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/src/git_copilot_commit/settings.py +0 -0
  16. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/src/git_copilot_commit/version.py +0 -0
  17. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/uv.lock +0 -0
  18. {git_copilot_commit-0.1.20 → git_copilot_commit-0.2.1}/vhs/demo.vhs +0 -0
@@ -0,0 +1,56 @@
1
+ # List available commands
2
+ [private]
3
+ default:
4
+ @just --list
5
+
6
+ # Pass all arguments directly to git-copilot-commit
7
+ commit *args:
8
+ uv run git-copilot-commit commit {{args}}
9
+
10
+
11
+ # Bump version based on GitHub tags and create empty commit
12
+ bump type="patch":
13
+ #!/usr/bin/env bash
14
+ set -euo pipefail
15
+
16
+ # Get the latest tag from GitHub
17
+ echo "Fetching latest tag from GitHub..."
18
+ latest_tag=$(gh release list --limit 1 --json tagName --jq '.[0].tagName // "v0.0.0"')
19
+
20
+ # Remove 'v' prefix if present
21
+ version=${latest_tag#v}
22
+
23
+ # Parse version components
24
+ IFS='.' read -r major minor patch <<< "$version"
25
+
26
+ # Bump based on type
27
+ case "{{type}}" in
28
+ major)
29
+ major=$((major + 1))
30
+ minor=0
31
+ patch=0
32
+ ;;
33
+ minor)
34
+ minor=$((minor + 1))
35
+ patch=0
36
+ ;;
37
+ patch)
38
+ patch=$((patch + 1))
39
+ ;;
40
+ *)
41
+ echo "Error: Invalid bump type '{{type}}'. Use: major, minor, or patch"
42
+ exit 1
43
+ ;;
44
+ esac
45
+
46
+ # Create new version
47
+ new_version="v${major}.${minor}.${patch}"
48
+
49
+ echo "Current version: $latest_tag"
50
+ echo "New version: $new_version"
51
+
52
+ # Create empty commit
53
+ git commit --allow-empty -m "Bump version to $new_version"
54
+
55
+ echo "✓ Created empty commit for $new_version"
56
+ echo " Next: Create and push tag with: git tag $new_version && git push && git push --tags"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-copilot-commit
3
- Version: 0.1.20
3
+ Version: 0.2.1
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
@@ -14,7 +14,7 @@ from pathlib import Path
14
14
 
15
15
  from pycopilot.copilot import Copilot, CopilotAPIError # type: ignore
16
16
  from pycopilot.auth import Authentication
17
- from .git import GitRepository, GitError, NotAGitRepositoryError, GitStatus
17
+ from .git import GitRepository, GitError, NotAGitRepositoryError
18
18
  from .settings import Settings
19
19
  from .version import __version__
20
20
 
@@ -24,7 +24,7 @@ app = typer.Typer(help=__doc__, add_completion=False)
24
24
 
25
25
  def version_callback(value: bool):
26
26
  if value:
27
- rich.print(f"git-copilot-commit [bold green]{__version__}[/]")
27
+ rich.print(f"git-copilot-commit [bold yellow]{__version__}[/]")
28
28
  raise typer.Exit()
29
29
 
30
30
 
@@ -46,7 +46,7 @@ def main(
46
46
  # Don't show version for print command to avoid interfering with pipes
47
47
  if ctx.invoked_subcommand != "echo":
48
48
  console.print(
49
- f"[bold]{(__package__ or 'git_copilot_commit').replace('_', '-')}[/] - [bold blue]v{__version__}[/]\n"
49
+ f"[bold]{(__package__ or 'git_copilot_commit').replace('_', '-')}[/] - [bold green]v{__version__}[/]\n"
50
50
  )
51
51
 
52
52
 
@@ -88,41 +88,56 @@ def load_system_prompt() -> str:
88
88
 
89
89
 
90
90
  def generate_commit_message(
91
- repo: GitRepository, status: GitStatus, model: str | None = None
91
+ repo: GitRepository, model: str | None = None, context: str = ""
92
92
  ) -> str:
93
93
  """Generate a conventional commit message using Copilot API."""
94
94
 
95
+ # Refresh status after staging
96
+ status = repo.get_status()
97
+
98
+ if not status.has_staged_changes:
99
+ console.print("[red]No staged changes to commit.[/red]")
100
+ raise typer.Exit()
101
+
95
102
  system_prompt = load_system_prompt()
96
103
  client = Copilot(system_prompt=system_prompt)
97
104
 
98
- prompt = f"""
99
- `git status`:
100
-
101
- ```
102
- {status.get_porcelain_output()}
103
- ```
105
+ prompt_parts = [
106
+ "`git status`:\n",
107
+ f"```\n{status.get_porcelain_output()}\n```",
108
+ "\n\n`git diff --staged`:\n",
109
+ f"```\n{status.staged_diff}\n```",
110
+ ]
104
111
 
105
- `git diff --staged`:
112
+ if context.strip():
113
+ prompt_parts.insert(0, f"User-provided context:\n\n{context.strip()}\n\n")
106
114
 
107
- ```
108
- {status.staged_diff}
109
- ```
115
+ prompt_parts.append("\nGenerate a conventional commit message:")
110
116
 
111
- Generate a conventional commit message:"""
117
+ prompt = "\n".join(prompt_parts)
112
118
 
113
119
  try:
120
+ client.reset()
114
121
  response = client.ask(prompt, model=model) if model else client.ask(prompt)
115
122
  return response.content
116
123
  except CopilotAPIError:
117
- # Fallback to git status only when diff is too large
118
- fallback_prompt = f"""`git status`:
124
+ fallback_prompt_parts = [
125
+ "`git status`:\n",
126
+ f"```\n{status.get_porcelain_output()}\n```",
127
+ ]
128
+
129
+ if context.strip():
130
+ fallback_prompt_parts.insert(
131
+ 0, f"User-provided context:\n\n{context.strip()}\n\n"
132
+ )
119
133
 
120
- ```
121
- {status.get_porcelain_output()}
122
- ```
134
+ fallback_prompt_parts.append(
135
+ "\nGenerate a conventional commit message based on the git status above:"
136
+ )
123
137
 
124
- Generate a conventional commit message based on the git status above:"""
138
+ fallback_prompt = "\n".join(fallback_prompt_parts)
125
139
 
140
+ client.reset()
126
141
  response = (
127
142
  client.ask(fallback_prompt, model=model)
128
143
  if model
@@ -142,6 +157,12 @@ def commit(
142
157
  yes: bool = typer.Option(
143
158
  False, "--yes", "-y", help="Automatically accept the generated commit message"
144
159
  ),
160
+ context: str = typer.Option(
161
+ "",
162
+ "--context",
163
+ "-c",
164
+ help="Optional user-provided context to guide commit message",
165
+ ),
145
166
  ):
146
167
  """
147
168
  Generate commit message based on changes in the current git repository and commit them.
@@ -189,25 +210,29 @@ def commit(
189
210
  repo.stage_files()
190
211
  console.print("[green]Staged untracked files.[/green]")
191
212
 
192
- # Refresh status after staging
193
- status = repo.get_status()
194
-
195
- if not status.has_staged_changes:
196
- console.print("[yellow]No staged changes to commit.[/yellow]")
197
- raise typer.Exit()
213
+ if context:
214
+ console.print(
215
+ Panel(context.strip(), title="User Context", border_style="magenta")
216
+ )
198
217
 
199
218
  # Generate or use provided commit message
200
219
  with console.status(
201
- "[cyan]Generating commit message based on [bold]`git diff --staged`[/bold] ...[/cyan]"
220
+ "[yellow]Generating commit message based on [bold]`git diff --staged`[/] ...[/yellow]"
202
221
  ):
203
- commit_message = generate_commit_message(repo, status, model)
222
+ commit_message = generate_commit_message(repo, model, context=context)
204
223
 
205
224
  console.print(
206
- "[cyan]Generated commit message based on [bold]`git diff --staged`[/bold] ...[/cyan]"
225
+ "[yellow]Generated commit message based on [bold]`git diff --staged`[/] ...[/yellow]"
207
226
  )
208
227
 
209
228
  # Display commit message
210
- console.print(Panel(commit_message, title="Commit Message", border_style="green"))
229
+ console.print(
230
+ Panel(
231
+ f"[bold]{commit_message}[/]",
232
+ title="Commit Message",
233
+ border_style="cyan",
234
+ )
235
+ )
211
236
 
212
237
  # Confirm commit or edit message (skip if --yes flag is used)
213
238
  if yes:
@@ -349,7 +374,7 @@ def echo(
349
374
 
350
375
  # Generate commit message from the input
351
376
  prompt = f"""
352
- git diff:
377
+ `git diff --staged`:
353
378
 
354
379
  ```
355
380
  {input_text.strip()}
@@ -0,0 +1,62 @@
1
+ # Commit Message Generator System Prompt
2
+
3
+ You are a Git commit message assistant trained to write a single clear, structured, and informative commit message following the Conventional Commits specification. You will receive:
4
+
5
+ 1. A `git diff --staged` output (or a summary of changed files)
6
+ 2. Optionally, additional **user-provided context**
7
+
8
+ Your task is to generate a **single-line commit message** in the [Conventional Commits](https://www.conventionalcommits.org/) format based on both inputs. If no context is provided, rely **only** on the diff.
9
+
10
+ ## ✅ Output Format
11
+
12
+ ```
13
+ <type>(<optional scope>): <description>
14
+ ```
15
+
16
+ - Do not include a body or footer.
17
+ - Do not wrap the message in backticks or code blocks.
18
+ - Keep the title line ≤72 characters.
19
+
20
+ ## ✅ Valid Types
21
+
22
+ - `feat`: New feature
23
+ - `fix`: Bug fix
24
+ - `docs`: Documentation changes
25
+ - `style`: Code formatting (no logic changes)
26
+ - `refactor`: Code restructuring (no behavior changes)
27
+ - `perf`: Performance improvements
28
+ - `test`: Adding or updating tests
29
+ - `chore`: Maintenance tasks (e.g., CI/CD, dependencies)
30
+ - `revert`: Revert of a previous commit
31
+
32
+ ## ✅ Scope (Optional)
33
+
34
+ - Lowercase, single word or hyphenated phrase
35
+ - Represents the affected area, module, or file
36
+ - Use broad area if multiple related files are affected
37
+
38
+ ## ✅ Subject Line
39
+
40
+ - Use imperative mood ("remove" not "removed")
41
+ - Focus on **what** changed, not why or how
42
+ - Be concise and specific
43
+ - Use abbreviations (e.g., "config" not "configuration")
44
+
45
+ ## ✅ Using User-Provided Context
46
+
47
+ - If additional context is provided by the user, you may **incorporate it** to clarify purpose (e.g., "remove duplicate entry").
48
+ - If no such context is provided, **do not speculate or infer**.
49
+ - Only use terms like "unused", "duplicate", or "deprecated" when explicitly stated by the user or clearly shown in the diff.
50
+
51
+ ## ❌ Do Not
52
+
53
+ - Do not use vague phrases ("made changes", "updated code")
54
+ - Do not use past tense ("added", "removed")
55
+ - Do not explain implementation or reasoning ("to fix bug", "because of issue")
56
+ - Do not guess purpose based on intuition or incomplete file context
57
+
58
+ ---
59
+
60
+ Given a Git diff, a list of modified files, or a short description of changes, generate a single, short, clear and structured Conventional Commit message following the above rules. If multiple changes are detected, prioritize the most important changes in a single commit message. Do not add any body or footer. You can only give one reply for each conversation.
61
+
62
+ Do not wrap the response in triple backticks or single backticks. Return the commit message as the output without any additional text, explanations, or formatting markers.
@@ -1,70 +0,0 @@
1
- # Commit Message Generator System Prompt
2
-
3
- You are a Git commit message assistant trained to write a single clear, structured, and informative commit message following the Conventional Commits specification based on the provided `git diff --staged` output.
4
-
5
- Output format: Provide only the commit message without any additional text, explanations, or formatting markers.
6
-
7
- The guidelines for the commit messages are as follows:
8
-
9
- ## 1. Format
10
-
11
- ```
12
- <type>[optional scope]: <description>
13
- ```
14
-
15
- - The first line (title) should be at most 72 characters long.
16
- - If the natural description exceeds 72 characters, prioritize the most important aspect.
17
- - Use abbreviations when appropriate: `config` not `configuration`.
18
- - The body (if present) should be wrapped at 100 characters per line.
19
-
20
- ## 2. Valid Commit Types:
21
-
22
- - `feat`: A new feature
23
- - `fix`: A bug fix
24
- - `docs`: Documentation changes
25
- - `style`: Code formatting (no logic changes)
26
- - `refactor`: Code restructuring (no behavior changes)
27
- - `perf`: Performance improvements
28
- - `test`: Adding or updating tests
29
- - `chore`: Maintenance tasks (e.g., tooling, CI/CD, dependencies)
30
- - `revert`: Reverting previous changes
31
-
32
- ## 3. Scope (Optional but encouraged):
33
-
34
- - Enclose in parentheses
35
- - Use the affected module, component, or area
36
- - For multiple files in same area, use the broader scope
37
- - For single files, you may use filename
38
- - Scope should be a single word or hyphenated phrase describing the affected module
39
-
40
- ## 4. Description:
41
-
42
- - Use imperative mood (e.g., "add feature" instead of "added" or "adds").
43
- - Be concise yet informative.
44
- - Focus on the primary change, not all details.
45
- - Do not make assumptions about why the change was made or how it works.
46
- - When bumping versions, do not mention the names of the files.
47
-
48
- ## 5. Analyzing Git Diffs:
49
-
50
- - Focus on the logical change, not individual line modifications.
51
- - Group related file changes under one logical scope.
52
- - Identify the primary purpose of the change set.
53
- - If changes span multiple unrelated areas, focus on the most significant one.
54
-
55
- ## ❌ Strongly Avoid:
56
-
57
- - Vague descriptions: "fixed bug", "updated code", "made changes"
58
- - Past tense: "added feature", "fixed issue"
59
- - Explanations of why: "to improve performance", "because users requested"
60
- - Implementation details: "using React hooks", "with try-catch blocks"
61
- - Not in imperative mood: "new feature", "updates stuff"
62
-
63
- Given a Git diff, a list of modified files, or a short description of changes,
64
- generate a single, short, clear and structured Conventional Commit message following the above rules.
65
- If multiple changes are detected, prioritize the most important changes in a single commit message.
66
- Do not add any body or footer.
67
- You can only give one reply for each conversation.
68
-
69
- Do not wrap the response in triple backticks or single backticks.
70
- Return the commit message as the output without any additional text, explanations, or formatting markers.