gitforge-cli 0.1.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.
- gitforge_cli-0.1.0/LICENSE +22 -0
- gitforge_cli-0.1.0/PKG-INFO +130 -0
- gitforge_cli-0.1.0/README.md +99 -0
- gitforge_cli-0.1.0/gitforge/__init__.py +4 -0
- gitforge_cli-0.1.0/gitforge/__main__.py +8 -0
- gitforge_cli-0.1.0/gitforge/changelog.py +101 -0
- gitforge_cli-0.1.0/gitforge/cli.py +530 -0
- gitforge_cli-0.1.0/gitforge/git.py +255 -0
- gitforge_cli-0.1.0/gitforge/templates.py +67 -0
- gitforge_cli-0.1.0/gitforge_cli.egg-info/PKG-INFO +130 -0
- gitforge_cli-0.1.0/gitforge_cli.egg-info/SOURCES.txt +15 -0
- gitforge_cli-0.1.0/gitforge_cli.egg-info/dependency_links.txt +1 -0
- gitforge_cli-0.1.0/gitforge_cli.egg-info/entry_points.txt +2 -0
- gitforge_cli-0.1.0/gitforge_cli.egg-info/requires.txt +5 -0
- gitforge_cli-0.1.0/gitforge_cli.egg-info/top_level.txt +1 -0
- gitforge_cli-0.1.0/pyproject.toml +47 -0
- gitforge_cli-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 shazeus
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gitforge-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A practical Git workflow automation tool for branches, snapshots, releases, and repository hygiene.
|
|
5
|
+
Author-email: shazeus <efeborazan07@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/shazeus/gitforge-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/shazeus/gitforge-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/shazeus/gitforge-cli/issues
|
|
10
|
+
Keywords: git,cli,workflow,automation,release,changelog
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: click>=8.1
|
|
27
|
+
Requires-Dist: rich>=13.7
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
<h1 align="center">GitForge</h1>
|
|
34
|
+
<p align="center">Practical Git workflow automation for branches, snapshots, releases, and repository hygiene.</p>
|
|
35
|
+
<p align="center">
|
|
36
|
+
<a href="https://pypi.org/project/gitforge-cli/"><img alt="PyPI" src="https://img.shields.io/pypi/v/gitforge-cli.svg"></a>
|
|
37
|
+
<a href="https://pypi.org/project/gitforge-cli/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/gitforge-cli.svg"></a>
|
|
38
|
+
<a href="https://github.com/shazeus/gitforge-cli/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/shazeus/gitforge-cli.svg"></a>
|
|
39
|
+
<a href="https://github.com/shazeus/gitforge-cli/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/shazeus/gitforge-cli.svg?style=social"></a>
|
|
40
|
+
</p>
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
GitForge is a terminal-first Git workflow assistant for developers who want repeatable branch naming, safer commits, fast repository health checks, release tags, changelogs, branch cleanup, and ref comparisons without memorizing a pile of shell snippets. It uses the real Git executable, prints clean Rich tables, and keeps every operation explicit so it fits normal local and CI workflows.
|
|
46
|
+
|
|
47
|
+
- **Repository health checks** - inspect branch, upstream, dirty state, remotes, conflicts, and local Git identity.
|
|
48
|
+
- **Branch automation** - turn ticket titles into consistent branch names and optionally switch to them.
|
|
49
|
+
- **Snapshot commits** - stage tracked or all files, commit with guardrails, and optionally push.
|
|
50
|
+
- **Release tagging** - create annotated semantic-version tags with dirty-tree protection.
|
|
51
|
+
- **Changelog generation** - group commit history into Markdown or JSON output.
|
|
52
|
+
- **Cleanup and compare tools** - remove merged branches safely and summarize ref differences.
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install gitforge-cli
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The installed console command is:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
gitforge --help
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Usage
|
|
67
|
+
|
|
68
|
+
Inspect a repository:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
gitforge status --repo .
|
|
72
|
+
gitforge doctor --repo .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Create a workflow branch:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
gitforge branch "Add OAuth callback validation" --ticket AUTH-42 --prefix feature
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Commit a snapshot:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
gitforge snapshot -m "Implement OAuth callback validation"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Generate a changelog:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
gitforge changelog --since v0.1.0 --output CHANGELOG.md
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Create a release tag:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
gitforge release 1.2.0 --push
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Commands
|
|
100
|
+
|
|
101
|
+
| Command | Description | Example |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `gitforge status` | Show branch, upstream, dirty state, remote, and last tag. | `gitforge status --json` |
|
|
104
|
+
| `gitforge doctor` | Check Git availability, repo state, identity, remote, upstream, and conflicts. | `gitforge doctor` |
|
|
105
|
+
| `gitforge branch <title>` | Create a normalized branch name from a ticket/title. | `gitforge branch "Fix login" --ticket WEB-7` |
|
|
106
|
+
| `gitforge snapshot` | Stage changes and commit with safety checks. | `gitforge snapshot -m "Fix login"` |
|
|
107
|
+
| `gitforge sync` | Fetch, pull with rebase or merge, and optionally push. | `gitforge sync --autostash` |
|
|
108
|
+
| `gitforge release <version>` | Create an annotated release tag. | `gitforge release 1.0.0` |
|
|
109
|
+
| `gitforge changelog` | Render commit history as grouped Markdown or JSON. | `gitforge changelog --max-count 25` |
|
|
110
|
+
| `gitforge compare <base> [head]` | Compare two refs by unique commits and changed files. | `gitforge compare main HEAD` |
|
|
111
|
+
| `gitforge cleanup` | List or delete merged local branches. | `gitforge cleanup --apply` |
|
|
112
|
+
| `gitforge ignore` | Append built-in `.gitignore` templates. | `gitforge ignore python macos` |
|
|
113
|
+
|
|
114
|
+
## Configuration
|
|
115
|
+
|
|
116
|
+
GitForge intentionally uses standard Git configuration instead of its own config file.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
git config user.name "Your Name"
|
|
120
|
+
git config user.email "you@example.com"
|
|
121
|
+
git remote add origin git@github.com:you/project.git
|
|
122
|
+
git branch --set-upstream-to origin/main main
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Most commands accept `--repo` so they can operate on another checkout without changing directories.
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT License. See [LICENSE](LICENSE).
|
|
130
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">GitForge</h1>
|
|
3
|
+
<p align="center">Practical Git workflow automation for branches, snapshots, releases, and repository hygiene.</p>
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://pypi.org/project/gitforge-cli/"><img alt="PyPI" src="https://img.shields.io/pypi/v/gitforge-cli.svg"></a>
|
|
6
|
+
<a href="https://pypi.org/project/gitforge-cli/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/gitforge-cli.svg"></a>
|
|
7
|
+
<a href="https://github.com/shazeus/gitforge-cli/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/shazeus/gitforge-cli.svg"></a>
|
|
8
|
+
<a href="https://github.com/shazeus/gitforge-cli/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/shazeus/gitforge-cli.svg?style=social"></a>
|
|
9
|
+
</p>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
GitForge is a terminal-first Git workflow assistant for developers who want repeatable branch naming, safer commits, fast repository health checks, release tags, changelogs, branch cleanup, and ref comparisons without memorizing a pile of shell snippets. It uses the real Git executable, prints clean Rich tables, and keeps every operation explicit so it fits normal local and CI workflows.
|
|
15
|
+
|
|
16
|
+
- **Repository health checks** - inspect branch, upstream, dirty state, remotes, conflicts, and local Git identity.
|
|
17
|
+
- **Branch automation** - turn ticket titles into consistent branch names and optionally switch to them.
|
|
18
|
+
- **Snapshot commits** - stage tracked or all files, commit with guardrails, and optionally push.
|
|
19
|
+
- **Release tagging** - create annotated semantic-version tags with dirty-tree protection.
|
|
20
|
+
- **Changelog generation** - group commit history into Markdown or JSON output.
|
|
21
|
+
- **Cleanup and compare tools** - remove merged branches safely and summarize ref differences.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install gitforge-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The installed console command is:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
gitforge --help
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
Inspect a repository:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gitforge status --repo .
|
|
41
|
+
gitforge doctor --repo .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Create a workflow branch:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
gitforge branch "Add OAuth callback validation" --ticket AUTH-42 --prefix feature
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Commit a snapshot:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
gitforge snapshot -m "Implement OAuth callback validation"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Generate a changelog:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
gitforge changelog --since v0.1.0 --output CHANGELOG.md
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Create a release tag:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
gitforge release 1.2.0 --push
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Commands
|
|
69
|
+
|
|
70
|
+
| Command | Description | Example |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| `gitforge status` | Show branch, upstream, dirty state, remote, and last tag. | `gitforge status --json` |
|
|
73
|
+
| `gitforge doctor` | Check Git availability, repo state, identity, remote, upstream, and conflicts. | `gitforge doctor` |
|
|
74
|
+
| `gitforge branch <title>` | Create a normalized branch name from a ticket/title. | `gitforge branch "Fix login" --ticket WEB-7` |
|
|
75
|
+
| `gitforge snapshot` | Stage changes and commit with safety checks. | `gitforge snapshot -m "Fix login"` |
|
|
76
|
+
| `gitforge sync` | Fetch, pull with rebase or merge, and optionally push. | `gitforge sync --autostash` |
|
|
77
|
+
| `gitforge release <version>` | Create an annotated release tag. | `gitforge release 1.0.0` |
|
|
78
|
+
| `gitforge changelog` | Render commit history as grouped Markdown or JSON. | `gitforge changelog --max-count 25` |
|
|
79
|
+
| `gitforge compare <base> [head]` | Compare two refs by unique commits and changed files. | `gitforge compare main HEAD` |
|
|
80
|
+
| `gitforge cleanup` | List or delete merged local branches. | `gitforge cleanup --apply` |
|
|
81
|
+
| `gitforge ignore` | Append built-in `.gitignore` templates. | `gitforge ignore python macos` |
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
GitForge intentionally uses standard Git configuration instead of its own config file.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
git config user.name "Your Name"
|
|
89
|
+
git config user.email "you@example.com"
|
|
90
|
+
git remote add origin git@github.com:you/project.git
|
|
91
|
+
git branch --set-upstream-to origin/main main
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Most commands accept `--repo` so they can operate on another checkout without changing directories.
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT License. See [LICENSE](LICENSE).
|
|
99
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Changelog extraction and rendering."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import asdict, dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from .git import git_text
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class CommitEntry:
|
|
13
|
+
"""A Git commit prepared for display."""
|
|
14
|
+
|
|
15
|
+
full_hash: str
|
|
16
|
+
short_hash: str
|
|
17
|
+
subject: str
|
|
18
|
+
author: str
|
|
19
|
+
date: str
|
|
20
|
+
group: str
|
|
21
|
+
|
|
22
|
+
def as_dict(self) -> dict[str, str]:
|
|
23
|
+
return asdict(self)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
GROUP_LABELS = {
|
|
27
|
+
"feat": "Features",
|
|
28
|
+
"fix": "Fixes",
|
|
29
|
+
"docs": "Documentation",
|
|
30
|
+
"test": "Tests",
|
|
31
|
+
"perf": "Performance",
|
|
32
|
+
"refactor": "Refactors",
|
|
33
|
+
"build": "Build",
|
|
34
|
+
"ci": "CI",
|
|
35
|
+
"other": "Other",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def classify_subject(subject: str) -> str:
|
|
40
|
+
"""Classify a commit using conventional-commit style prefixes."""
|
|
41
|
+
|
|
42
|
+
prefix = subject.split(":", 1)[0].lower()
|
|
43
|
+
prefix = prefix.split("(", 1)[0]
|
|
44
|
+
return prefix if prefix in GROUP_LABELS else "other"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def load_commits(
|
|
48
|
+
repo: str | Path,
|
|
49
|
+
*,
|
|
50
|
+
rev_range: str | None = None,
|
|
51
|
+
max_count: int = 100,
|
|
52
|
+
) -> list[CommitEntry]:
|
|
53
|
+
"""Load commits from git log."""
|
|
54
|
+
|
|
55
|
+
pretty = "%H%x1f%h%x1f%s%x1f%an%x1f%ad%x1e"
|
|
56
|
+
args = ["log", f"--max-count={max_count}", "--date=short", f"--pretty=format:{pretty}"]
|
|
57
|
+
if rev_range:
|
|
58
|
+
args.insert(1, rev_range)
|
|
59
|
+
output = git_text(args, repo)
|
|
60
|
+
commits: list[CommitEntry] = []
|
|
61
|
+
for record in output.split("\x1e"):
|
|
62
|
+
record = record.strip()
|
|
63
|
+
if not record:
|
|
64
|
+
continue
|
|
65
|
+
parts = record.split("\x1f")
|
|
66
|
+
if len(parts) != 5:
|
|
67
|
+
continue
|
|
68
|
+
full_hash, short_hash, subject, author, date = parts
|
|
69
|
+
commits.append(
|
|
70
|
+
CommitEntry(
|
|
71
|
+
full_hash=full_hash,
|
|
72
|
+
short_hash=short_hash,
|
|
73
|
+
subject=subject,
|
|
74
|
+
author=author,
|
|
75
|
+
date=date,
|
|
76
|
+
group=classify_subject(subject),
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
return commits
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def render_markdown(commits: list[CommitEntry], title: str = "Changelog") -> str:
|
|
83
|
+
"""Render commits as grouped Markdown."""
|
|
84
|
+
|
|
85
|
+
if not commits:
|
|
86
|
+
return f"## {title}\n\nNo commits found for the selected range.\n"
|
|
87
|
+
|
|
88
|
+
lines = [f"## {title}", ""]
|
|
89
|
+
for group, label in GROUP_LABELS.items():
|
|
90
|
+
group_commits = [commit for commit in commits if commit.group == group]
|
|
91
|
+
if not group_commits:
|
|
92
|
+
continue
|
|
93
|
+
lines.append(f"### {label}")
|
|
94
|
+
for commit in group_commits:
|
|
95
|
+
lines.append(
|
|
96
|
+
f"- `{commit.short_hash}` {commit.subject} "
|
|
97
|
+
f"({commit.author}, {commit.date})"
|
|
98
|
+
)
|
|
99
|
+
lines.append("")
|
|
100
|
+
return "\n".join(lines).rstrip() + "\n"
|
|
101
|
+
|