commithygiene 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.
- commithygiene-0.1.0/LICENSE +21 -0
- commithygiene-0.1.0/PKG-INFO +236 -0
- commithygiene-0.1.0/README.md +214 -0
- commithygiene-0.1.0/commithygiene.egg-info/PKG-INFO +236 -0
- commithygiene-0.1.0/commithygiene.egg-info/SOURCES.txt +10 -0
- commithygiene-0.1.0/commithygiene.egg-info/dependency_links.txt +1 -0
- commithygiene-0.1.0/commithygiene.egg-info/entry_points.txt +2 -0
- commithygiene-0.1.0/commithygiene.egg-info/top_level.txt +1 -0
- commithygiene-0.1.0/commithygiene.py +492 -0
- commithygiene-0.1.0/pyproject.toml +31 -0
- commithygiene-0.1.0/setup.cfg +4 -0
- commithygiene-0.1.0/tests/test_commithygiene.py +181 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 commithygiene contributors
|
|
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.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: commithygiene
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Read-only linter for noisy, AI-generated git commit history
|
|
5
|
+
Author: commithygiene contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: git,commits,linter,ai,agent,cli,ci
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# commithygiene
|
|
24
|
+
|
|
25
|
+
<div align="center">
|
|
26
|
+
|
|
27
|
+
**The read-only linter for AI-mangled git history.**
|
|
28
|
+
|
|
29
|
+
[](https://www.python.org/downloads/)
|
|
30
|
+
[](#-zero-dependencies)
|
|
31
|
+
[](LICENSE)
|
|
32
|
+
[](tests/)
|
|
33
|
+
|
|
34
|
+
*AI agents write a lot of commits. Some of them deserve to be squashed before anyone sees them.*
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## What problem does this solve?
|
|
41
|
+
|
|
42
|
+
Your AI coding agent (or you, at 2 a.m.) just produced this history:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
a1b2c3d Update LoginForm.tsx
|
|
46
|
+
d4e5f6 Fix TypeScript error
|
|
47
|
+
g7h8i9 Revert LoginForm.tsx
|
|
48
|
+
j0k1l2 Update LoginForm.tsx again
|
|
49
|
+
m3n4o5 Fix import
|
|
50
|
+
p6q7r8 wip
|
|
51
|
+
s9t0u1 LoginForm complete
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Seven commits. One component. **History that is useless for bisect, hostile to review, and embarrassing to merge.**
|
|
55
|
+
|
|
56
|
+
`commithygiene` finds these commits — *before* they hit your branch. It's read-only: it never rewrites history, never stages files, never touches your reflog. It just **reads** and **reports**. You decide what to do.
|
|
57
|
+
|
|
58
|
+
> **AI wrote the code. You're still responsible for the history.**
|
|
59
|
+
|
|
60
|
+
## Why commithygiene?
|
|
61
|
+
|
|
62
|
+
Every other tool in this space wants to *rewrite* your history:
|
|
63
|
+
|
|
64
|
+
| Tool | Approach | Needs | Can it gate CI? |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| Claude `git-squash` skill | Interactive squash | Claude Code runtime | ❌ Lives in a chat session |
|
|
67
|
+
| `commit-tidy` / `squash-commits` skills | LLM-guided rebase | Claude + context | ❌ |
|
|
68
|
+
| `yawn` | AI *writes new* commit messages | API key | ❌ |
|
|
69
|
+
| `git-shrink` | Group + squash by similarity | Node.js + npm | ⚠️ Rewrites history |
|
|
70
|
+
| **commithygiene** | **Read-only linter with exit codes** | **Just Python 3.10+** | ✅ **Made for CI** |
|
|
71
|
+
|
|
72
|
+
The ecosystem had `prettier` but no `eslint`. `git-cliff` but no `shellcheck`. **commithygiene is the linter** — the thing you put in your pipeline to *catch* noise, not the thing you run interactively to fix it.
|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
- 🔒 **Read-only by design** — `git log` and `git show` only. Zero risk of destroying history.
|
|
77
|
+
- 🪶 **Zero dependencies** — one file, pure Python standard library. No npm, no Rust toolchain, no API key.
|
|
78
|
+
- 🤖 **Knows AI fingerprints** — detects `wip`, `fix typo again`, `revert the revert`, `actually works now`, and other agent churn patterns.
|
|
79
|
+
- 🚦 **CI-ready exit codes** — `0` clean, `1` noise found, `2` error. `--strict` promotes warnings to errors.
|
|
80
|
+
- 📊 **JSON output** — machine-readable for scripts, bots, and dashboards.
|
|
81
|
+
- 📈 **Health reports** — `report` gives you a project-wide noise ratio and verdict.
|
|
82
|
+
- 🐍 **Python 3.10+** — runs anywhere Python runs. Windows, macOS, Linux.
|
|
83
|
+
|
|
84
|
+
## Quick start
|
|
85
|
+
|
|
86
|
+
### 1. Drop it in
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# No install needed — it's a single file.
|
|
90
|
+
curl -O https://raw.githubusercontent.com/DEL8108/commit-hygiene-checker/main/commithygiene.py
|
|
91
|
+
python commithygiene.py check
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Or install properly:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install git+https://github.com/DEL8108/commit-hygiene-checker.git
|
|
98
|
+
commithygiene check
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 2. Run it on your current branch
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
$ commithygiene check
|
|
105
|
+
|
|
106
|
+
commithygiene — scanned 8 commit(s)
|
|
107
|
+
|
|
108
|
+
✗ noise-subject 650b5e8c43 noise commit: 'wip'
|
|
109
|
+
✗ noise-subject 9743088c03 noise commit: 'wip'
|
|
110
|
+
! churn-subject 562493cd3e possible churn commit: 'fix typo again'
|
|
111
|
+
! churn-subject 5871f1d5c1 possible churn commit: 'actually works now'
|
|
112
|
+
! churn-subject a4590d7b47 possible churn commit: 'revert the revert'
|
|
113
|
+
! trivial-only 4ffd15159e tiny diff touching only trivial files (README.md)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Exit code `1` — your CI just found noise before your reviewer did.
|
|
117
|
+
|
|
118
|
+
### 3. Gate your PRs
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
# .github/workflows/hygiene.yml
|
|
122
|
+
name: Commit Hygiene
|
|
123
|
+
on: [pull_request]
|
|
124
|
+
jobs:
|
|
125
|
+
hygiene:
|
|
126
|
+
runs-on: ubuntu-latest
|
|
127
|
+
steps:
|
|
128
|
+
- uses: actions/checkout@v4
|
|
129
|
+
with:
|
|
130
|
+
fetch-depth: 0 # need full history
|
|
131
|
+
- uses: actions/setup-python@v5
|
|
132
|
+
with:
|
|
133
|
+
python-version: "3.12"
|
|
134
|
+
- name: Check commit hygiene
|
|
135
|
+
run: |
|
|
136
|
+
curl -O https://raw.githubusercontent.com/DEL8108/commit-hygiene-checker/main/commithygiene.py
|
|
137
|
+
python commithygiene.py check "${{ github.event.pull_request.base.sha }}..HEAD" --strict
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Now every PR with a `wip` or an `actually works now` in it gets flagged **before merge**.
|
|
141
|
+
|
|
142
|
+
## Usage
|
|
143
|
+
|
|
144
|
+
### `check` — find noisy commits
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
commithygiene check # scan all of HEAD
|
|
148
|
+
commithygiene check HEAD~20..HEAD # scan the last 20 commits
|
|
149
|
+
commithygiene check main..HEAD # only commits on this branch
|
|
150
|
+
commithygiene check --strict # warnings become errors (exit 1)
|
|
151
|
+
commithygiene check --format json # machine-readable output
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `report` — project-wide health
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
$ commithygiene report
|
|
158
|
+
|
|
159
|
+
commit hygiene report — HEAD
|
|
160
|
+
|
|
161
|
+
commits : 128
|
|
162
|
+
noise commits : 31 (24%)
|
|
163
|
+
churn commits : 12 (9%)
|
|
164
|
+
verdict : very noisy
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Exit codes
|
|
168
|
+
|
|
169
|
+
| Code | Meaning |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `0` | Clean — no noise, or only warnings (without `--strict`) |
|
|
172
|
+
| `1` | Noise found — errors, or warnings under `--strict` |
|
|
173
|
+
| `2` | Usage / I/O error (not a git repo, bad range, git missing) |
|
|
174
|
+
|
|
175
|
+
## What gets flagged
|
|
176
|
+
|
|
177
|
+
| Rule | Severity | Example |
|
|
178
|
+
|---|---|---|
|
|
179
|
+
| `noise-subject` | error | `wip`, `tmp`, `fixup!`, `???`, `initial commit`, `checkpoint` |
|
|
180
|
+
| `churn-subject` | warning | `fix typo again`, `revert the revert`, `actually works now`, `for real this time` |
|
|
181
|
+
| `trivial-only` | warning | a 1-file commit touching only `README.md`, lockfiles, `.gitignore` |
|
|
182
|
+
|
|
183
|
+
Warnings stay warnings unless you pass `--strict` — because sometimes a `revert` is a legitimate, deliberate decision. `commithygiene` errs on the side of *showing* you, not *blocking* you.
|
|
184
|
+
|
|
185
|
+
## How it works
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
git log --format=%H <range> # list commits, oldest first
|
|
189
|
+
│
|
|
190
|
+
▼
|
|
191
|
+
git show --numstat --format=%s <h> # subject + per-file stats per commit
|
|
192
|
+
│
|
|
193
|
+
▼
|
|
194
|
+
heuristic engine # noise patterns, churn tokens, trivial paths
|
|
195
|
+
│
|
|
196
|
+
▼
|
|
197
|
+
findings ──► table / json ──► exit code 0/1/2
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
No git history is modified at any step. The only commands executed are `git log`, `git show`, and `git rev-parse`. You can audit the entire tool in one sitting — it's ~500 lines.
|
|
201
|
+
|
|
202
|
+
## Why "hygiene"?
|
|
203
|
+
|
|
204
|
+
Because that's what it is. Like flossing, nobody *wants* to think about commit hygiene, but the alternative is worse. The name also means the tool is easily discoverable apart from the squash/rewrite crowd — this is the *prevention* layer, not the *surgery* layer.
|
|
205
|
+
|
|
206
|
+
## Limitations
|
|
207
|
+
|
|
208
|
+
Being read-only and heuristic-driven means some things are out of scope, on purpose:
|
|
209
|
+
|
|
210
|
+
- **It never rewrites history.** For that, use `git rebase -i`, `git-squash`, or `git-shrink`.
|
|
211
|
+
- **It judges by signals, not semantics.** A `wip` with a giant meaningful diff is still flagged — you know your repo better than the heuristic does.
|
|
212
|
+
- **It doesn't verify build state.** Two commits both labeled `fix` could each be perfectly fine.
|
|
213
|
+
- **No AI, no LLM calls, no telemetry.** It's deterministic. The same input always produces the same output. That's a feature.
|
|
214
|
+
|
|
215
|
+
## Contributing
|
|
216
|
+
|
|
217
|
+
Found a noise pattern the tool missed? A false positive? Contributions are welcome:
|
|
218
|
+
|
|
219
|
+
1. Fork and clone the repo.
|
|
220
|
+
2. Run the tests: `python -m unittest discover -s tests -v`
|
|
221
|
+
3. Add a test for your pattern in `tests/test_commithygiene.py`.
|
|
222
|
+
4. Open a PR with a clear description.
|
|
223
|
+
|
|
224
|
+
The whole philosophy is "small, conservative, zero false-positive pressure." New rules need example commits that prove the signal is real.
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT — see [LICENSE](LICENSE). Do whatever you want with it; attribution appreciated.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
<div align="center">
|
|
233
|
+
|
|
234
|
+
**Star it if your agent's commit history has ever made you say "what is this?"** ⭐
|
|
235
|
+
|
|
236
|
+
</div>
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# commithygiene
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**The read-only linter for AI-mangled git history.**
|
|
6
|
+
|
|
7
|
+
[](https://www.python.org/downloads/)
|
|
8
|
+
[](#-zero-dependencies)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](tests/)
|
|
11
|
+
|
|
12
|
+
*AI agents write a lot of commits. Some of them deserve to be squashed before anyone sees them.*
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## What problem does this solve?
|
|
19
|
+
|
|
20
|
+
Your AI coding agent (or you, at 2 a.m.) just produced this history:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
a1b2c3d Update LoginForm.tsx
|
|
24
|
+
d4e5f6 Fix TypeScript error
|
|
25
|
+
g7h8i9 Revert LoginForm.tsx
|
|
26
|
+
j0k1l2 Update LoginForm.tsx again
|
|
27
|
+
m3n4o5 Fix import
|
|
28
|
+
p6q7r8 wip
|
|
29
|
+
s9t0u1 LoginForm complete
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Seven commits. One component. **History that is useless for bisect, hostile to review, and embarrassing to merge.**
|
|
33
|
+
|
|
34
|
+
`commithygiene` finds these commits — *before* they hit your branch. It's read-only: it never rewrites history, never stages files, never touches your reflog. It just **reads** and **reports**. You decide what to do.
|
|
35
|
+
|
|
36
|
+
> **AI wrote the code. You're still responsible for the history.**
|
|
37
|
+
|
|
38
|
+
## Why commithygiene?
|
|
39
|
+
|
|
40
|
+
Every other tool in this space wants to *rewrite* your history:
|
|
41
|
+
|
|
42
|
+
| Tool | Approach | Needs | Can it gate CI? |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| Claude `git-squash` skill | Interactive squash | Claude Code runtime | ❌ Lives in a chat session |
|
|
45
|
+
| `commit-tidy` / `squash-commits` skills | LLM-guided rebase | Claude + context | ❌ |
|
|
46
|
+
| `yawn` | AI *writes new* commit messages | API key | ❌ |
|
|
47
|
+
| `git-shrink` | Group + squash by similarity | Node.js + npm | ⚠️ Rewrites history |
|
|
48
|
+
| **commithygiene** | **Read-only linter with exit codes** | **Just Python 3.10+** | ✅ **Made for CI** |
|
|
49
|
+
|
|
50
|
+
The ecosystem had `prettier` but no `eslint`. `git-cliff` but no `shellcheck`. **commithygiene is the linter** — the thing you put in your pipeline to *catch* noise, not the thing you run interactively to fix it.
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- 🔒 **Read-only by design** — `git log` and `git show` only. Zero risk of destroying history.
|
|
55
|
+
- 🪶 **Zero dependencies** — one file, pure Python standard library. No npm, no Rust toolchain, no API key.
|
|
56
|
+
- 🤖 **Knows AI fingerprints** — detects `wip`, `fix typo again`, `revert the revert`, `actually works now`, and other agent churn patterns.
|
|
57
|
+
- 🚦 **CI-ready exit codes** — `0` clean, `1` noise found, `2` error. `--strict` promotes warnings to errors.
|
|
58
|
+
- 📊 **JSON output** — machine-readable for scripts, bots, and dashboards.
|
|
59
|
+
- 📈 **Health reports** — `report` gives you a project-wide noise ratio and verdict.
|
|
60
|
+
- 🐍 **Python 3.10+** — runs anywhere Python runs. Windows, macOS, Linux.
|
|
61
|
+
|
|
62
|
+
## Quick start
|
|
63
|
+
|
|
64
|
+
### 1. Drop it in
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# No install needed — it's a single file.
|
|
68
|
+
curl -O https://raw.githubusercontent.com/DEL8108/commit-hygiene-checker/main/commithygiene.py
|
|
69
|
+
python commithygiene.py check
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or install properly:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install git+https://github.com/DEL8108/commit-hygiene-checker.git
|
|
76
|
+
commithygiene check
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 2. Run it on your current branch
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
$ commithygiene check
|
|
83
|
+
|
|
84
|
+
commithygiene — scanned 8 commit(s)
|
|
85
|
+
|
|
86
|
+
✗ noise-subject 650b5e8c43 noise commit: 'wip'
|
|
87
|
+
✗ noise-subject 9743088c03 noise commit: 'wip'
|
|
88
|
+
! churn-subject 562493cd3e possible churn commit: 'fix typo again'
|
|
89
|
+
! churn-subject 5871f1d5c1 possible churn commit: 'actually works now'
|
|
90
|
+
! churn-subject a4590d7b47 possible churn commit: 'revert the revert'
|
|
91
|
+
! trivial-only 4ffd15159e tiny diff touching only trivial files (README.md)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Exit code `1` — your CI just found noise before your reviewer did.
|
|
95
|
+
|
|
96
|
+
### 3. Gate your PRs
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
# .github/workflows/hygiene.yml
|
|
100
|
+
name: Commit Hygiene
|
|
101
|
+
on: [pull_request]
|
|
102
|
+
jobs:
|
|
103
|
+
hygiene:
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4
|
|
107
|
+
with:
|
|
108
|
+
fetch-depth: 0 # need full history
|
|
109
|
+
- uses: actions/setup-python@v5
|
|
110
|
+
with:
|
|
111
|
+
python-version: "3.12"
|
|
112
|
+
- name: Check commit hygiene
|
|
113
|
+
run: |
|
|
114
|
+
curl -O https://raw.githubusercontent.com/DEL8108/commit-hygiene-checker/main/commithygiene.py
|
|
115
|
+
python commithygiene.py check "${{ github.event.pull_request.base.sha }}..HEAD" --strict
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Now every PR with a `wip` or an `actually works now` in it gets flagged **before merge**.
|
|
119
|
+
|
|
120
|
+
## Usage
|
|
121
|
+
|
|
122
|
+
### `check` — find noisy commits
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
commithygiene check # scan all of HEAD
|
|
126
|
+
commithygiene check HEAD~20..HEAD # scan the last 20 commits
|
|
127
|
+
commithygiene check main..HEAD # only commits on this branch
|
|
128
|
+
commithygiene check --strict # warnings become errors (exit 1)
|
|
129
|
+
commithygiene check --format json # machine-readable output
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### `report` — project-wide health
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
$ commithygiene report
|
|
136
|
+
|
|
137
|
+
commit hygiene report — HEAD
|
|
138
|
+
|
|
139
|
+
commits : 128
|
|
140
|
+
noise commits : 31 (24%)
|
|
141
|
+
churn commits : 12 (9%)
|
|
142
|
+
verdict : very noisy
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Exit codes
|
|
146
|
+
|
|
147
|
+
| Code | Meaning |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `0` | Clean — no noise, or only warnings (without `--strict`) |
|
|
150
|
+
| `1` | Noise found — errors, or warnings under `--strict` |
|
|
151
|
+
| `2` | Usage / I/O error (not a git repo, bad range, git missing) |
|
|
152
|
+
|
|
153
|
+
## What gets flagged
|
|
154
|
+
|
|
155
|
+
| Rule | Severity | Example |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `noise-subject` | error | `wip`, `tmp`, `fixup!`, `???`, `initial commit`, `checkpoint` |
|
|
158
|
+
| `churn-subject` | warning | `fix typo again`, `revert the revert`, `actually works now`, `for real this time` |
|
|
159
|
+
| `trivial-only` | warning | a 1-file commit touching only `README.md`, lockfiles, `.gitignore` |
|
|
160
|
+
|
|
161
|
+
Warnings stay warnings unless you pass `--strict` — because sometimes a `revert` is a legitimate, deliberate decision. `commithygiene` errs on the side of *showing* you, not *blocking* you.
|
|
162
|
+
|
|
163
|
+
## How it works
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
git log --format=%H <range> # list commits, oldest first
|
|
167
|
+
│
|
|
168
|
+
▼
|
|
169
|
+
git show --numstat --format=%s <h> # subject + per-file stats per commit
|
|
170
|
+
│
|
|
171
|
+
▼
|
|
172
|
+
heuristic engine # noise patterns, churn tokens, trivial paths
|
|
173
|
+
│
|
|
174
|
+
▼
|
|
175
|
+
findings ──► table / json ──► exit code 0/1/2
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
No git history is modified at any step. The only commands executed are `git log`, `git show`, and `git rev-parse`. You can audit the entire tool in one sitting — it's ~500 lines.
|
|
179
|
+
|
|
180
|
+
## Why "hygiene"?
|
|
181
|
+
|
|
182
|
+
Because that's what it is. Like flossing, nobody *wants* to think about commit hygiene, but the alternative is worse. The name also means the tool is easily discoverable apart from the squash/rewrite crowd — this is the *prevention* layer, not the *surgery* layer.
|
|
183
|
+
|
|
184
|
+
## Limitations
|
|
185
|
+
|
|
186
|
+
Being read-only and heuristic-driven means some things are out of scope, on purpose:
|
|
187
|
+
|
|
188
|
+
- **It never rewrites history.** For that, use `git rebase -i`, `git-squash`, or `git-shrink`.
|
|
189
|
+
- **It judges by signals, not semantics.** A `wip` with a giant meaningful diff is still flagged — you know your repo better than the heuristic does.
|
|
190
|
+
- **It doesn't verify build state.** Two commits both labeled `fix` could each be perfectly fine.
|
|
191
|
+
- **No AI, no LLM calls, no telemetry.** It's deterministic. The same input always produces the same output. That's a feature.
|
|
192
|
+
|
|
193
|
+
## Contributing
|
|
194
|
+
|
|
195
|
+
Found a noise pattern the tool missed? A false positive? Contributions are welcome:
|
|
196
|
+
|
|
197
|
+
1. Fork and clone the repo.
|
|
198
|
+
2. Run the tests: `python -m unittest discover -s tests -v`
|
|
199
|
+
3. Add a test for your pattern in `tests/test_commithygiene.py`.
|
|
200
|
+
4. Open a PR with a clear description.
|
|
201
|
+
|
|
202
|
+
The whole philosophy is "small, conservative, zero false-positive pressure." New rules need example commits that prove the signal is real.
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT — see [LICENSE](LICENSE). Do whatever you want with it; attribution appreciated.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
<div align="center">
|
|
211
|
+
|
|
212
|
+
**Star it if your agent's commit history has ever made you say "what is this?"** ⭐
|
|
213
|
+
|
|
214
|
+
</div>
|