Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions skills/ce-commit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ Treat this as a snapshot. Re-read branch and staged set immediately before commi
- Good: `Fix double-submit on checkout`
- Good: `Add per-subscription mute (U3)`

6. **Stage and commit** — stage **named files only** (never `git add -A` or `git add .`). Honor `exclude:<paths>` when the invocation carries it: those files stay uncommitted no matter what else changed; say in the report that they were left out. Prefer one shell call per commit group:
6. **Stage and commit** — stage **named files only** (never `git add -A` or `git add .`). Honor `exclude:<paths>` when the invocation carries it: those files stay uncommitted no matter what else changed; say in the report that they were left out. Write the full message — subject line, blank line, optional body — to a file outside the repo with your file-write tool, then stage and commit as two calls per commit group:

```bash
git add file1 file2 file3 && git commit -m "$(cat <<'EOF'
type(scope): subject line here
git add file1 file2 file3
```

Optional body when the why is not obvious from the subject.
EOF
)" -- file1 file2 file3
```bash
git commit -F <message-file> -- file1 file2 file3
```

No shell parses the message with `-F`: a `$`, quotes, backticks, or a multi-line body pass through literally under any shell, with no quoting rules to satisfy. Git's normal whitespace cleanup still applies (trailing spaces trimmed, blank-line runs collapsed), which is fine for a commit message.

The trailing path list on `git commit` is load-bearing: a bare `git commit` takes the whole index, so anything already staged before this run (a caller's `exclude:` paths, or work the user staged and did not name) would ride into the commit. Naming the paths commits exactly the group and leaves other index entries alone.

7. **Confirm** — `git status`; report hash(es) and subject(s).
3 changes: 2 additions & 1 deletion tests/ce-commit-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ describe("ce-commit contract", () => {
expect(content).toMatch(/never `git add -A` or `git add \.`/)
expect(content).toContain("named files")
expect(content).toContain("git add file1 file2 file3")
expect(content).toContain("<<'EOF'")
expect(content).toContain("git commit -F <message-file>")
expect(content).toContain("-- file1 file2 file3")
})

test("defaults fix over feat and leads messages with outcome", async () => {
Expand Down