docs(git): add tracked AI commit workflow prompt

Introduce `.github/prompts/commit.prompt.md` as the contributor-facing description
of how assistants should stage, review, propose, and record commits.

- Document defaults: one file per commit, rare justified pairs, no blanket `git add`.
- Describe optional `.githooks/pre-commit` cap at two staged paths.
- Require reading the full `git diff --staged` (no truncation) before messaging.
- Spell out approval-before-commit flow and Conventional Commits subject lines.
- Scale the body to the patch: short summaries for small edits; large or
  multi-concern diffs need grouped, substantive bullets so history stays readable.
- Keep checklist items aligned with that depth expectation.
This commit is contained in:
Jukka Aho
2026-05-09 16:44:31 +03:00
parent 3af1067aeb
commit 0182fc7566
+175
View File
@@ -0,0 +1,175 @@
# Git Commit Workflow for AI Assistants
## Goals
- Git history should read as a **story**: small steps, one clear intent per commit.
- **Default:** one file per commit (smallest practical unit).
- **Exception:** several files in **one** commit only when they share the **same logical entity / same story** (incomplete or misleading if split). This should be **unusual**—always prefer smaller commits when in doubt.
## When to combine files (exception)
Combine only when splitting would:
- leave the tree broken or the feature half-wired, or
- tell an incoherent story (e.g. rename without updating the only call site).
**Always** state **why** those paths belong together in one commit when proposing a multi-file commit.
## User initiation
```
❌ AI: "Should I commit these files?"
❌ AI: "Let me commit this..."
✅ Human: "Commit the changed files"
✅ Human: "Do the commits now"
```
**Rule:** Do not suggest or initiate commits. Only run this workflow after an explicit user command.
## Staging
```bash
git add path/to/file.jl
# or, only when justified:
git add path/a.jl path/b.jl
```
- Avoid `git add .` and `git add -A` unless the user explicitly wants everything (still read the full staged diff after).
- Never stage unrelated changes into the same commit.
## Optional git hook (max two staged paths)
The repo ships `.githooks/pre-commit`. After `git config core.hooksPath .githooks`, commits with **more than two** staged files are rejected. This supports the common “impl + test” or “snippet + verifier” pair without allowing large batches. Split bigger changes across commits or adjust the hook deliberately.
## Read the full staged diff
```bash
git diff --staged
```
**Critical:**
- Do not pipe through `head`, `tail`, `less`, or otherwise truncate.
- Read every line; the commit message must reflect the actual diff.
**Exception:** machine-generated or binary files—review only as far as is practical.
## Approval before `git commit`
**Before** running `git commit`, present to the user:
1. **File(s)** to be committed (exact paths).
2. **Full proposed commit message** (subject + body in the format below).
3. If **more than one file:** a **short justification** why one commit is appropriate.
**Wait** for explicit approval. Only then:
```bash
git commit -F- <<'EOF'
<paste full message>
EOF
```
(or equivalent multi-line `-m` usage). Do not commit silently.
## Commit message structure
**1. Subject line (first line)** — Conventional Commits:
`type(scope): specific description from the diff`
- Types include `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, etc.
- `scope` is optional but recommended when it clarifies the area.
- Imperative mood; specific; no vague "update" / "fix things".
**2. Blank line**
**3. Summary** — one short paragraph, **one to three sentences**: what changed and why, for this commit only.
**4. Body detail (scale with the diff)** — after the summary:
- **Small / localized change:** optional bullets only when they add real value; often the summary is enough.
- **Large file, large diff, or several concerns in one commit:** expand with **substantive bullets**. Prefer **grouped sections** (short headings or bullet groups) that mirror the patch: major types/functions added, behavior changes, wiring/exports, migrations, risks, or follow-ups. A few vague bullets are not sufficient when the diff is hundreds of lines or touches multiple subsystems—the message should let a reviewer reconstruct *why* the patch looks the way it does without re-reading every hunk.
Use `-` bullet lists; omit sections that do not apply.
### Example (single file)
```
refactor(basis): Replace per-element lagrange includes with generator entrypoints
The basis tree previously listed seven separate lagrange_*.jl includes; they are
folded behind lagrange_generator.jl and lagrange_generated.jl so new elements
register in one place.
- Drop redundant includes from JuliaFEM.jl
- Document the 'Basis' suffix convention in the include comment
```
### Example (multi-file — requires justification to user)
When proposing:
> **Files:** `src/foo.jl`, `test/foo/test_foo.jl`
> **Why one commit:** adds `compute_bar` and the regression test that locks its behavior; splitting would leave the feature untested in history.
> **Message:** …
## Cycle per commit
1. Stage the smallest set (usually one file).
2. `git diff --staged` — read all of it.
3. Propose message + paths (+ multi-file justification if needed).
4. Wait for approval.
5. Commit.
6. Repeat for remaining work.
## Common mistakes
### Vague or mismatched messages
```bash
# ❌ WRONG
git commit -m "Update documentation"
# ✅ RIGHT — subject + summary (+ bullets if needed), from the real diff
```
### Bundling unrelated files
```bash
# ❌ WRONG — two different stories
git add docs/CONTRIBUTING.md src/unrelated_fix.jl
# ✅ RIGHT — two commits, or ask user to split worktrees if mixed in one working tree
```
### Committing without approval
Never run `git commit` until the user has approved the proposed paths and message.
### Truncating the diff
Never use `git diff --staged | head` (etc.). Read the full diff.
## Checklist before each commit
- [ ] Did the user explicitly ask to commit?
- [ ] Is the staged set as **small** as it reasonably can be?
- [ ] If multiple files: is there a **clear single story**, and will you **justify** it to the user?
- [ ] If `.githooks` is active: are there **at most two** staged paths?
- [ ] Did I read the **full** `git diff --staged`?
- [ ] Subject line: Conventional Commits, specific, matches diff?
- [ ] Body: blank line, then **13 sentence** summary, then **bullets scaled to diff size** (rich, grouped bullets for large / multi-concern commits)?
- [ ] Did I **propose** the commit and wait for **approval** before `git commit`?
## Why this matters
1. **Story:** History is easy to read and bisect.
2. **Review:** Each commit is reviewable in isolation.
3. **Honesty:** Messages match what the diff actually does.
4. **Control:** The author approves each step.
---
Git history is long-lived. Prefer small, well-explained commits and explicit approval before each `git commit`.