git-explain 2.1.8__tar.gz → 2.2.0__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_explain-2.2.0/PKG-INFO +111 -0
- git_explain-2.2.0/README.md +80 -0
- git_explain-2.2.0/git_explain/__init__.py +1 -0
- git_explain-2.2.0/git_explain/__main__.py +3 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain/cli.py +56 -49
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain/commit_infer.py +1 -1
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain/gemini.py +101 -47
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain/heuristics.py +39 -21
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain/path_topics.py +80 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain/run.py +46 -2
- git_explain-2.2.0/git_explain.egg-info/PKG-INFO +111 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain.egg-info/SOURCES.txt +1 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/pyproject.toml +5 -2
- {git_explain-2.1.8 → git_explain-2.2.0}/tests/test_cli_utils.py +10 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/tests/test_gemini.py +54 -31
- {git_explain-2.1.8 → git_explain-2.2.0}/tests/test_heuristics.py +3 -3
- {git_explain-2.1.8 → git_explain-2.2.0}/tests/test_run_apply.py +20 -1
- git_explain-2.1.8/PKG-INFO +0 -168
- git_explain-2.1.8/README.md +0 -137
- git_explain-2.1.8/git_explain/__init__.py +0 -1
- git_explain-2.1.8/git_explain.egg-info/PKG-INFO +0 -168
- {git_explain-2.1.8 → git_explain-2.2.0}/LICENSE +0 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain/git.py +0 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain.egg-info/dependency_links.txt +0 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain.egg-info/entry_points.txt +0 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain.egg-info/requires.txt +0 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/git_explain.egg-info/top_level.txt +0 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/setup.cfg +0 -0
- {git_explain-2.1.8 → git_explain-2.2.0}/tests/test_commit_infer.py +0 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: git-explain
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: CLI that suggests git add/commit from diffs using Gemini
|
|
5
|
+
Author: nazarli-shabnam
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/nazarli-shabnam/git-explain
|
|
8
|
+
Project-URL: Source, https://github.com/nazarli-shabnam/git-explain
|
|
9
|
+
Keywords: git,cli,commit,ai,gemini
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: google-genai>=1.50.0
|
|
23
|
+
Requires-Dist: typer>=0.12.0
|
|
24
|
+
Requires-Dist: rich>=13.0.0
|
|
25
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
26
|
+
Requires-Dist: prompt_toolkit>=3.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff>=0.8.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# git-explain
|
|
33
|
+
|
|
34
|
+
**Commit message block?** Run this in your repo after you change files. It suggests `git add` and `git commit` lines you can copy—or apply in one step if you want. **Nothing leaves your machine** unless you turn on AI.
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/git-explain/)
|
|
37
|
+
[](https://github.com/nazarli-shabnam/git-explain/tags)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Install (Python 3.10+)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install git-explain
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**From source** (this repo):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Clone:** install deps (`requirements.txt` is fine), `cd` into the repo, then:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python -m git_explain
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Run that from the repo root so Python picks up the `git_explain` folder—no `pip install -e .` needed.
|
|
61
|
+
|
|
62
|
+
Optional: install a specific tag from GitHub instead of PyPI:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install "git+https://github.com/nazarli-shabnam/git-explain.git@v2.1.8"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Try it
|
|
71
|
+
|
|
72
|
+
1. In any git repo, change or add a file (not ignored).
|
|
73
|
+
2. Run:
|
|
74
|
+
```bash
|
|
75
|
+
git-explain
|
|
76
|
+
```
|
|
77
|
+
3. Choose what to include (`all` is fine), read the suggestion, answer **`n`** if you only want to copy commands yourself—nothing bad happens.
|
|
78
|
+
|
|
79
|
+
Heuristics guess a sensible type and message from paths and statuses. **No account, no key, no network** for that path.
|
|
80
|
+
|
|
81
|
+
Suggested commits follow **[Conventional Commits](https://www.conventionalcommits.org/)**—`feat: …`, `fix: …`, optional `(scope)`, and so on—so changelogs and release tools can read them.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Optional: Gemini
|
|
86
|
+
|
|
87
|
+
If you want sharper messages, set **`GEMINI_API_KEY`** (or `GOOGLE_API_KEY`) in the environment or a **`.env`** file in the folder where you run the tool.
|
|
88
|
+
|
|
89
|
+
| Command | In plain terms |
|
|
90
|
+
|--------|----------------|
|
|
91
|
+
| `git-explain --ai` | AI sees **paths and change type** only (no file contents). |
|
|
92
|
+
| `git-explain --ai --with-diff` | AI also sees the **diff**—better detail; only use if you’re OK sending that to the API. |
|
|
93
|
+
| `git-explain --suggest` | **Staged only**; prints one plain `git commit -m "…"` line (easy to copy). Needs AI; don’t combine with other flags. |
|
|
94
|
+
|
|
95
|
+
Everything else (`--auto`, `--staged-only`, `--cwd`, model override, shell completion): **`git-explain --help`**.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## If Gemini complains
|
|
100
|
+
|
|
101
|
+
- **429 / quota** — wait a bit, or try the default model; see Google’s [rate limits](https://ai.google.dev/gemini-api/docs/rate-limits).
|
|
102
|
+
- **404 / model not found** — set something current, e.g. **`GEMINI_MODEL=gemini-2.5-flash`**, and check their [model list](https://ai.google.dev/api/models).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Developers
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install -e ".[dev]"
|
|
110
|
+
pytest -q
|
|
111
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# git-explain
|
|
2
|
+
|
|
3
|
+
**Commit message block?** Run this in your repo after you change files. It suggests `git add` and `git commit` lines you can copy—or apply in one step if you want. **Nothing leaves your machine** unless you turn on AI.
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/git-explain/)
|
|
6
|
+
[](https://github.com/nazarli-shabnam/git-explain/tags)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install (Python 3.10+)
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install git-explain
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**From source** (this repo):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install -e .
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Clone:** install deps (`requirements.txt` is fine), `cd` into the repo, then:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m git_explain
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Run that from the repo root so Python picks up the `git_explain` folder—no `pip install -e .` needed.
|
|
30
|
+
|
|
31
|
+
Optional: install a specific tag from GitHub instead of PyPI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install "git+https://github.com/nazarli-shabnam/git-explain.git@v2.1.8"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Try it
|
|
40
|
+
|
|
41
|
+
1. In any git repo, change or add a file (not ignored).
|
|
42
|
+
2. Run:
|
|
43
|
+
```bash
|
|
44
|
+
git-explain
|
|
45
|
+
```
|
|
46
|
+
3. Choose what to include (`all` is fine), read the suggestion, answer **`n`** if you only want to copy commands yourself—nothing bad happens.
|
|
47
|
+
|
|
48
|
+
Heuristics guess a sensible type and message from paths and statuses. **No account, no key, no network** for that path.
|
|
49
|
+
|
|
50
|
+
Suggested commits follow **[Conventional Commits](https://www.conventionalcommits.org/)**—`feat: …`, `fix: …`, optional `(scope)`, and so on—so changelogs and release tools can read them.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Optional: Gemini
|
|
55
|
+
|
|
56
|
+
If you want sharper messages, set **`GEMINI_API_KEY`** (or `GOOGLE_API_KEY`) in the environment or a **`.env`** file in the folder where you run the tool.
|
|
57
|
+
|
|
58
|
+
| Command | In plain terms |
|
|
59
|
+
|--------|----------------|
|
|
60
|
+
| `git-explain --ai` | AI sees **paths and change type** only (no file contents). |
|
|
61
|
+
| `git-explain --ai --with-diff` | AI also sees the **diff**—better detail; only use if you’re OK sending that to the API. |
|
|
62
|
+
| `git-explain --suggest` | **Staged only**; prints one plain `git commit -m "…"` line (easy to copy). Needs AI; don’t combine with other flags. |
|
|
63
|
+
|
|
64
|
+
Everything else (`--auto`, `--staged-only`, `--cwd`, model override, shell completion): **`git-explain --help`**.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## If Gemini complains
|
|
69
|
+
|
|
70
|
+
- **429 / quota** — wait a bit, or try the default model; see Google’s [rate limits](https://ai.google.dev/gemini-api/docs/rate-limits).
|
|
71
|
+
- **404 / model not found** — set something current, e.g. **`GEMINI_MODEL=gemini-2.5-flash`**, and check their [model list](https://ai.google.dev/api/models).
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Developers
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install -e ".[dev]"
|
|
79
|
+
pytest -q
|
|
80
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.0"
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""CLI for git-explain: suggest and optionally apply commit message from diffs."""
|
|
2
2
|
|
|
3
|
+
import re
|
|
3
4
|
import subprocess
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
+
from dataclasses import dataclass, replace
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Iterable
|
|
7
8
|
|
|
@@ -11,14 +12,18 @@ from rich.console import Console
|
|
|
11
12
|
from rich.panel import Panel
|
|
12
13
|
from rich.text import Text
|
|
13
14
|
|
|
14
|
-
from git_explain.gemini import suggest_commands
|
|
15
|
+
from git_explain.gemini import Suggestion, suggest_commands
|
|
15
16
|
from git_explain.heuristics import suggest_from_changes
|
|
16
17
|
from git_explain.git import (
|
|
17
18
|
get_combined_diff,
|
|
18
19
|
get_diff_for_paths,
|
|
19
20
|
get_staged_diff_for_paths,
|
|
20
21
|
)
|
|
21
|
-
from git_explain.run import
|
|
22
|
+
from git_explain.run import (
|
|
23
|
+
apply_commands,
|
|
24
|
+
format_commit_message,
|
|
25
|
+
normalize_commit_subject_for_dash_m,
|
|
26
|
+
)
|
|
22
27
|
|
|
23
28
|
load_dotenv()
|
|
24
29
|
app = typer.Typer()
|
|
@@ -55,9 +60,8 @@ def _parse_combined(combined: str) -> tuple[bool | None, list[Change]]:
|
|
|
55
60
|
if v in ("true", "false"):
|
|
56
61
|
has_commits = v == "true"
|
|
57
62
|
continue
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
63
|
+
# A/M/D/R/C: add/modify/delete/rename/copy; T: type change; U: unmerged (git name-status)
|
|
64
|
+
m = re.match(r"^([AMDRCUT])\s+(.+)$", line, re.IGNORECASE)
|
|
61
65
|
if not m:
|
|
62
66
|
continue
|
|
63
67
|
status = m.group(1).upper()
|
|
@@ -343,13 +347,11 @@ def run(
|
|
|
343
347
|
)
|
|
344
348
|
raise typer.Exit(1)
|
|
345
349
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
title="Suggested commit command",
|
|
350
|
-
border_style="green",
|
|
351
|
-
)
|
|
350
|
+
cmsg = normalize_commit_subject_for_dash_m(sug.commit_message)
|
|
351
|
+
full = format_commit_message(
|
|
352
|
+
sug.commit_type, cmsg, scope=sug.scope, breaking=sug.breaking
|
|
352
353
|
)
|
|
354
|
+
print(f'git commit -m "{full}"')
|
|
353
355
|
return
|
|
354
356
|
|
|
355
357
|
if staged_only:
|
|
@@ -421,9 +423,8 @@ def run(
|
|
|
421
423
|
|
|
422
424
|
def suggest_for(
|
|
423
425
|
change_items: list[tuple[str, str]], title: str
|
|
424
|
-
) -> tuple[
|
|
425
|
-
|
|
426
|
-
# ai_fallback_reason is set when --ai was used but heuristics were used instead.
|
|
426
|
+
) -> tuple[Suggestion, str | None]:
|
|
427
|
+
"""Return (suggestion, ai_fallback_reason)."""
|
|
427
428
|
paths_for_infer = [p for _, p in change_items]
|
|
428
429
|
infer_diff: str | None = None
|
|
429
430
|
if paths_for_infer:
|
|
@@ -443,7 +444,7 @@ def run(
|
|
|
443
444
|
if diff_text:
|
|
444
445
|
payload = payload + "\n\n## Diff\n" + diff_text
|
|
445
446
|
try:
|
|
446
|
-
sug,
|
|
447
|
+
sug, _raw = suggest_commands(
|
|
447
448
|
payload,
|
|
448
449
|
model=model,
|
|
449
450
|
with_diff=with_diff,
|
|
@@ -451,27 +452,20 @@ def run(
|
|
|
451
452
|
)
|
|
452
453
|
if sug is None:
|
|
453
454
|
raise RuntimeError("Could not parse AI suggestion.")
|
|
454
|
-
return sug
|
|
455
|
+
return sug, None
|
|
455
456
|
except Exception as e:
|
|
456
|
-
# Fall back to heuristics on quota / API errors
|
|
457
457
|
h = suggest_from_changes(
|
|
458
458
|
changes=change_items,
|
|
459
459
|
has_commits=has_commits,
|
|
460
460
|
diff_text=infer_diff,
|
|
461
461
|
)
|
|
462
|
-
return (
|
|
463
|
-
h.add_args,
|
|
464
|
-
h.commit_type,
|
|
465
|
-
h.commit_message,
|
|
466
|
-
"",
|
|
467
|
-
str(e),
|
|
468
|
-
)
|
|
462
|
+
return h, str(e)
|
|
469
463
|
h = suggest_from_changes(
|
|
470
464
|
changes=change_items,
|
|
471
465
|
has_commits=has_commits,
|
|
472
466
|
diff_text=infer_diff,
|
|
473
467
|
)
|
|
474
|
-
return h
|
|
468
|
+
return h, None
|
|
475
469
|
|
|
476
470
|
selected_pairs = [(ch.status, ch.path) for ch in selected]
|
|
477
471
|
unique_paths = {p for _, p in selected_pairs}
|
|
@@ -491,18 +485,18 @@ def run(
|
|
|
491
485
|
if mode_input in ("one", "split"):
|
|
492
486
|
mode = mode_input
|
|
493
487
|
|
|
494
|
-
plan: list[tuple[str,
|
|
488
|
+
plan: list[tuple[str, Suggestion]] = []
|
|
495
489
|
ai_fallback_notes: list[tuple[str, str]] = []
|
|
496
490
|
if mode == "split":
|
|
497
491
|
groups = _group_changes(selected_pairs)
|
|
498
492
|
for gname, items in groups.items():
|
|
499
|
-
|
|
500
|
-
plan.append((gname,
|
|
493
|
+
sug, fb = suggest_for(items, title=gname.capitalize())
|
|
494
|
+
plan.append((gname, sug))
|
|
501
495
|
if fb:
|
|
502
496
|
ai_fallback_notes.append((gname, fb))
|
|
503
497
|
else:
|
|
504
|
-
|
|
505
|
-
plan.append(("one",
|
|
498
|
+
sug, fb = suggest_for(selected_pairs, title="Selected")
|
|
499
|
+
plan.append(("one", sug))
|
|
506
500
|
if fb:
|
|
507
501
|
ai_fallback_notes.append(("", fb))
|
|
508
502
|
|
|
@@ -529,11 +523,15 @@ def run(
|
|
|
529
523
|
)
|
|
530
524
|
)
|
|
531
525
|
|
|
532
|
-
def _render_plan(pl: list[tuple[str,
|
|
526
|
+
def _render_plan(pl: list[tuple[str, Suggestion]]) -> str:
|
|
533
527
|
rendered: list[str] = []
|
|
534
|
-
for name,
|
|
535
|
-
add_line = "git add -A -- " + " ".join(_ps_quote(p) for p in
|
|
536
|
-
|
|
528
|
+
for name, sug in pl:
|
|
529
|
+
add_line = "git add -A -- " + " ".join(_ps_quote(p) for p in sug.add_args)
|
|
530
|
+
subj = normalize_commit_subject_for_dash_m(sug.commit_message)
|
|
531
|
+
full = format_commit_message(
|
|
532
|
+
sug.commit_type, subj, scope=sug.scope, breaking=sug.breaking
|
|
533
|
+
)
|
|
534
|
+
commit_line = f'git commit -m "{full}"'
|
|
537
535
|
rendered.append(f"### {name}\n{add_line}\n{commit_line}")
|
|
538
536
|
return "\n\n".join(rendered)
|
|
539
537
|
|
|
@@ -555,29 +553,35 @@ def run(
|
|
|
555
553
|
.lower()
|
|
556
554
|
)
|
|
557
555
|
if edit_choice in ("y", "yes"):
|
|
558
|
-
updated: list[tuple[str,
|
|
559
|
-
for name,
|
|
556
|
+
updated: list[tuple[str, Suggestion]] = []
|
|
557
|
+
for name, sug in plan:
|
|
558
|
+
current = format_commit_message(
|
|
559
|
+
sug.commit_type,
|
|
560
|
+
sug.commit_message,
|
|
561
|
+
scope=sug.scope,
|
|
562
|
+
breaking=sug.breaking,
|
|
563
|
+
)
|
|
560
564
|
console.print(
|
|
561
|
-
f"[dim]{name}:[/dim] current message: [bold]
|
|
565
|
+
f"[dim]{name}:[/dim] current message: [bold]{current}[/bold]"
|
|
562
566
|
)
|
|
563
567
|
try:
|
|
564
568
|
from prompt_toolkit import prompt as pt_prompt
|
|
565
569
|
|
|
566
570
|
new_msg = (
|
|
567
571
|
pt_prompt(
|
|
568
|
-
"New commit message (subject only,
|
|
569
|
-
default=
|
|
572
|
+
"New commit message (subject only, type/scope added automatically): ",
|
|
573
|
+
default=sug.commit_message,
|
|
570
574
|
).strip()
|
|
571
|
-
or
|
|
575
|
+
or sug.commit_message
|
|
572
576
|
)
|
|
573
577
|
except Exception:
|
|
574
578
|
new_msg = (
|
|
575
579
|
typer.prompt(
|
|
576
|
-
"New commit message (subject only,
|
|
577
|
-
default=
|
|
580
|
+
"New commit message (subject only, type/scope added automatically)",
|
|
581
|
+
default=sug.commit_message,
|
|
578
582
|
).strip()
|
|
579
|
-
) or
|
|
580
|
-
updated.append((name,
|
|
583
|
+
) or sug.commit_message
|
|
584
|
+
updated.append((name, replace(sug, commit_message=new_msg)))
|
|
581
585
|
plan = updated
|
|
582
586
|
console.print(
|
|
583
587
|
Panel(
|
|
@@ -599,13 +603,16 @@ def run(
|
|
|
599
603
|
do_apply = choice == "auto" or choice in ("y", "yes")
|
|
600
604
|
|
|
601
605
|
if do_apply:
|
|
602
|
-
for name,
|
|
606
|
+
for name, sug in plan:
|
|
603
607
|
try:
|
|
604
608
|
apply_commands(
|
|
605
609
|
repo_root,
|
|
606
|
-
[] if staged_only else
|
|
607
|
-
|
|
608
|
-
|
|
610
|
+
[] if staged_only else sug.add_args,
|
|
611
|
+
sug.commit_type,
|
|
612
|
+
sug.commit_message,
|
|
613
|
+
scope=sug.scope,
|
|
614
|
+
body=sug.body,
|
|
615
|
+
breaking=sug.breaking,
|
|
609
616
|
staged_only=staged_only,
|
|
610
617
|
)
|
|
611
618
|
console.print(f"[green]Commit created ({name}).[/green]")
|
|
@@ -47,7 +47,7 @@ def refine_type_and_message_from_diff(
|
|
|
47
47
|
when the diff matches known bugfix patterns.
|
|
48
48
|
"""
|
|
49
49
|
ct = (commit_type or "").upper()
|
|
50
|
-
if ct in ("DOCS", "TEST", "TESTS", "CHORE"):
|
|
50
|
+
if ct in ("DOCS", "TEST", "TESTS", "CHORE", "BUILD", "CI", "STYLE", "PERF"):
|
|
51
51
|
return commit_type, commit_message
|
|
52
52
|
|
|
53
53
|
subject = infer_fix_subject_from_diff(diff_text)
|