Commit — Conventional Commits with Branch Safety
You are staging and committing changes in a git repository using conventional commit conventions.
Arguments
$ARGUMENTS may contain any combination of:
| Flag |
Effect |
--amend |
Amend the previous commit instead of creating a new one |
--fixes #N |
Link commit to issue N with Fixes #N footer |
--closes #N |
Link commit to issue N with Closes #N footer |
--quick |
Skip confirmation prompt — auto-detect and commit immediately |
--wip |
Create a wip: <description> commit with no body required |
| (plain text) |
Used as the commit message description |
Step 1: Pre-flight Checks
- Run
git rev-parse --is-inside-work-tree to confirm this is a git repo. If not, stop and tell the user.
- Run
git status --porcelain to check for changes. If there are no staged, unstaged, or untracked changes, stop and tell the user there's nothing to commit.
- Check for detached HEAD with
git rev-parse --abbrev-ref HEAD. If it returns HEAD, warn the user they're in detached HEAD state and ask how to proceed.
Step 2: Branch Safety
- Get the current branch:
git rev-parse --abbrev-ref HEAD
- If the branch is any of:
main, master, develop, development, qa, prod, production, staging, release — warn the user that they're on a protected branch.
- Ask the user for a branch name, suggesting one based on the changes (see Step 3 for naming convention).
- Create the branch with
git checkout -b <branch-name>.
- If the user explicitly says they want to commit directly to the protected branch, proceed — but confirm once more before committing.
Step 3: Branch Naming Convention
When suggesting or creating branches, use this format:
<type>/<kebab-case-description>
- Type matches the conventional commit type:
feat, fix, refactor, docs, chore, test, style, perf, ci, build
- Description: 2-5 words, kebab-case, under 60 chars total
- Examples:
feat/add-user-auth, fix/null-check-parser, docs/update-api-reference, chore/bump-dependencies
Step 4: Analyze Changes
Run these commands to understand the full picture:
git diff — unstaged changes
git diff --cached — staged changes
git status --porcelain — all changes including untracked files
If diffs are large, read key changed files to understand the nature of the changes.
Breaking Change Detection
Scan the diff for signals that this is a breaking change:
- Removed or renamed public functions, classes, or exported symbols
- Changed function signatures (added required params, changed return types)
- Deleted files that other modules import
- Renamed environment variables or config keys
If breaking changes are detected:
- Add
! after the type/scope in the commit subject: feat(api)!: rename auth endpoint
- Add a
BREAKING CHANGE: footer describing what changed and migration steps
Step 5: Safety Scan
Check for sensitive files in the changeset. Warn and exclude any of these:
.env, .env.* (environment variables)
*.pem, *.key, *.p12, *.pfx (certificates/keys)
credentials.json, service-account.json (API credentials)
id_rsa, id_ed25519, *.pub (SSH keys)
*.sqlite, *.db (databases)
.npmrc, .pypirc (package registry auth)
*.secret, *_secret*
If any are found:
- Tell the user which files were excluded and why
- Suggest adding them to
.gitignore if not already present
- Proceed with the remaining files
Step 6: Stage Files
- Use
git add <file1> <file2> ... with explicit file paths. Never use git add -A or git add ..
- If there are already staged changes and no unstaged changes, skip staging and use what's already staged.
- If there are both staged and unstaged changes, ask the user whether to include the unstaged changes or commit only what's staged.
- If there are more than 15 files to stage, list them and confirm with the user before staging.
Step 7: Determine Commit Message
If --wip flag is present:
- Use
wip: <brief description of current state> as the commit message
- No body required, skip type detection
- Skip commit message validation rules (length/mood checks)
If $ARGUMENTS contains a message:
- If it's already in conventional commit format (e.g.,
fix: resolve null pointer), use it as-is.
- If it's a plain description (e.g.,
fix the login bug), convert it to conventional format.
If $ARGUMENTS is empty:
Auto-detect the commit type from the diff:
| Type |
Heuristic |
feat |
New files, new functions/methods/components, new exports |
fix |
Changes to existing logic, error handling, edge cases |
refactor |
Restructuring without behavior change, renames, moves |
docs |
Only .md files, comments, or docstrings changed |
chore |
Dependency updates, config files, maintenance |
test |
Test files added or modified |
style |
Formatting, whitespace, linting fixes |
perf |
Optimization, caching, reducing allocations |
ci |
CI/CD config files (.github/workflows, Jenkinsfile, etc.) |
build |
Build scripts, Dockerfile, Makefile changes |
Issue linking
If --fixes #N or --closes #N was passed in $ARGUMENTS, append the corresponding footer:
Fixes #123
or
Closes #456
Message format:
<type>(<optional-scope>): <imperative-description>
- Use imperative mood ("add", "fix", "update" — not "added", "fixes", "updated")
- Lowercase first word after the colon
- No period at the end
- Keep the subject line under 72 characters
- Add a body (separated by blank line) for non-trivial changes explaining why, not what
Commit Message Validation
Before committing, verify the message passes these checks:
- Subject line is under 72 characters
- No trailing period on the subject
- First word after the colon is lowercase
- Uses imperative mood (not past tense like "added", "fixed", "updated")
- Has a valid conventional commit type prefix
If any check fails, fix the message before proceeding.
Step 7.5: Amend Mode (--amend)
If --amend was passed in $ARGUMENTS:
- Run
git log --oneline -1 to show the commit being amended
- Run
git log -1 --format=%P to check parent count — refuse to amend merge commits
- Run
git log -1 --format=%H and git branch -r --contains HEAD to check if the commit has been pushed — warn the user if it has, as amending will require a force push
- Show the user the current commit message and the proposed changes
- Use
git commit --amend instead of git commit in Step 8
- If the user wants to change the message, use
git commit --amend -m "new message". Otherwise use git commit --amend --no-edit to keep the existing message.
Step 8: Confirm and Commit
If --quick flag is present:
- Skip the confirmation prompt
- Auto-detect the type, generate the message, stage, and commit immediately
- Still enforce safety scans (Step 5) and branch protection (Step 2)
- Still validate the commit message (Step 7)
- Show the post-commit summary (Step 9)
Standard flow:
Present a summary to the user:
Branch: <branch-name>
Staged: <number> file(s)
Message: <proposed commit message>
Files:
- path/to/file1.ts
- path/to/file2.ts
Step 9: Post-commit Summary
After a successful commit, show:
Committed: <short-hash> <commit message>
Branch: <branch-name>
Files: <count> changed
Then suggest: "Run git push to push your changes." — but do not execute git push.
Step 10: Multi-commit Workflow
When the user requests splitting changes into multiple commits (e.g., "commit these separately", "split into logical commits"):
- Group files by change type — separate features from fixes from refactors from docs
- Present the proposed grouping to the user:
Commit 1 (feat): path/to/new-feature.ts, path/to/component.tsx
Commit 2 (fix): path/to/bugfix.ts
Commit 3 (docs): README.md
- Let the user adjust groupings before proceeding
- Execute sequentially — stage and commit each group one at a time
- Show combined summary at the end:
Created 3 commits:
abc1234 feat(ui): add user profile component
def5678 fix(api): handle null response in auth
ghi9012 docs: update API reference
Edge Cases
- Only staged changes: Skip staging, commit what's already staged.
- Mixed staged/unstaged: Ask the user whether to include unstaged changes.
- Merge conflicts: If
git status shows merge conflicts, tell the user to resolve them first.
- Untracked files only: Ask the user which files to add.
- Detached HEAD: Warn and ask for instructions before committing.
- Empty diff after staging: If staged changes result in no diff (e.g., only whitespace), warn the user.
1---2name: commit3description: Stage and commit changes with conventional commit messages, with branch safety and auto-generated messages4---56# Commit — Conventional Commits with Branch Safety78You are staging and committing changes in a git repository using conventional commit conventions.910## Arguments1112`$ARGUMENTS` may contain any combination of:1314| Flag | Effect |15|------|--------|16| `--amend` | Amend the previous commit instead of creating a new one |17| `--fixes #N` | Link commit to issue N with `Fixes #N` footer |18| `--closes #N` | Link commit to issue N with `Closes #N` footer |19| `--quick` | Skip confirmation prompt — auto-detect and commit immediately |20| `--wip` | Create a `wip: <description>` commit with no body required |21| *(plain text)* | Used as the commit message description |2223## Step 1: Pre-flight Checks24251. Run `git rev-parse --is-inside-work-tree` to confirm this is a git repo. If not, stop and tell the user.262. Run `git status --porcelain` to check for changes. If there are no staged, unstaged, or untracked changes, stop and tell the user there's nothing to commit.273. Check for detached HEAD with `git rev-parse --abbrev-ref HEAD`. If it returns `HEAD`, warn the user they're in detached HEAD state and ask how to proceed.2829## Step 2: Branch Safety30311. Get the current branch: `git rev-parse --abbrev-ref HEAD`322. If the branch is any of: `main`, `master`, `develop`, `development`, `qa`, `prod`, `production`, `staging`, `release` — **warn the user** that they're on a protected branch.333. Ask the user for a branch name, suggesting one based on the changes (see Step 3 for naming convention).344. Create the branch with `git checkout -b <branch-name>`.355. If the user explicitly says they want to commit directly to the protected branch, proceed — but confirm once more before committing.3637## Step 3: Branch Naming Convention3839When suggesting or creating branches, use this format:4041```42<type>/<kebab-case-description>43```4445- **Type** matches the conventional commit type: `feat`, `fix`, `refactor`, `docs`, `chore`, `test`, `style`, `perf`, `ci`, `build`46- **Description**: 2-5 words, kebab-case, under 60 chars total47- Examples: `feat/add-user-auth`, `fix/null-check-parser`, `docs/update-api-reference`, `chore/bump-dependencies`4849## Step 4: Analyze Changes5051Run these commands to understand the full picture:52531. `git diff` — unstaged changes542. `git diff --cached` — staged changes553. `git status --porcelain` — all changes including untracked files5657If diffs are large, read key changed files to understand the nature of the changes.5859### Breaking Change Detection6061Scan the diff for signals that this is a breaking change:6263- **Removed or renamed** public functions, classes, or exported symbols64- **Changed function signatures** (added required params, changed return types)65- **Deleted files** that other modules import66- **Renamed environment variables** or config keys6768If breaking changes are detected:691. Add `!` after the type/scope in the commit subject: `feat(api)!: rename auth endpoint`702. Add a `BREAKING CHANGE:` footer describing what changed and migration steps7172## Step 5: Safety Scan7374Check for sensitive files in the changeset. **Warn and exclude** any of these:7576- `.env`, `.env.*` (environment variables)77- `*.pem`, `*.key`, `*.p12`, `*.pfx` (certificates/keys)78- `credentials.json`, `service-account.json` (API credentials)79- `id_rsa`, `id_ed25519`, `*.pub` (SSH keys)80- `*.sqlite`, `*.db` (databases)81- `.npmrc`, `.pypirc` (package registry auth)82- `*.secret`, `*_secret*`8384If any are found:851. Tell the user which files were excluded and why862. Suggest adding them to `.gitignore` if not already present873. Proceed with the remaining files8889## Step 6: Stage Files9091- Use `git add <file1> <file2> ...` with explicit file paths. **Never** use `git add -A` or `git add .`.92- If there are already staged changes and no unstaged changes, skip staging and use what's already staged.93- If there are both staged and unstaged changes, ask the user whether to include the unstaged changes or commit only what's staged.94- If there are more than 15 files to stage, list them and confirm with the user before staging.9596## Step 7: Determine Commit Message9798### If `--wip` flag is present:99- Use `wip: <brief description of current state>` as the commit message100- No body required, skip type detection101- Skip commit message validation rules (length/mood checks)102103### If `$ARGUMENTS` contains a message:104- If it's already in conventional commit format (e.g., `fix: resolve null pointer`), use it as-is.105- If it's a plain description (e.g., `fix the login bug`), convert it to conventional format.106107### If `$ARGUMENTS` is empty:108Auto-detect the commit type from the diff:109110| Type | Heuristic |111|------|-----------|112| `feat` | New files, new functions/methods/components, new exports |113| `fix` | Changes to existing logic, error handling, edge cases |114| `refactor` | Restructuring without behavior change, renames, moves |115| `docs` | Only `.md` files, comments, or docstrings changed |116| `chore` | Dependency updates, config files, maintenance |117| `test` | Test files added or modified |118| `style` | Formatting, whitespace, linting fixes |119| `perf` | Optimization, caching, reducing allocations |120| `ci` | CI/CD config files (`.github/workflows`, Jenkinsfile, etc.) |121| `build` | Build scripts, Dockerfile, Makefile changes |122123### Issue linking124If `--fixes #N` or `--closes #N` was passed in `$ARGUMENTS`, append the corresponding footer:125```126Fixes #123127```128or129```130Closes #456131```132133### Message format:134```135<type>(<optional-scope>): <imperative-description>136```137138- Use **imperative mood** ("add", "fix", "update" — not "added", "fixes", "updated")139- **Lowercase** first word after the colon140- **No period** at the end141- Keep the subject line **under 72 characters**142- Add a **body** (separated by blank line) for non-trivial changes explaining *why*, not *what*143144### Commit Message Validation145Before committing, verify the message passes these checks:1461. Subject line is under 72 characters1472. No trailing period on the subject1483. First word after the colon is lowercase1494. Uses imperative mood (not past tense like "added", "fixed", "updated")1505. Has a valid conventional commit type prefix151152If any check fails, fix the message before proceeding.153154## Step 7.5: Amend Mode (`--amend`)155156If `--amend` was passed in `$ARGUMENTS`:1571581. Run `git log --oneline -1` to show the commit being amended1592. Run `git log -1 --format=%P` to check parent count — **refuse to amend merge commits**1603. Run `git log -1 --format=%H` and `git branch -r --contains HEAD` to check if the commit has been pushed — **warn the user** if it has, as amending will require a force push1614. Show the user the current commit message and the proposed changes1625. Use `git commit --amend` instead of `git commit` in Step 81636. If the user wants to change the message, use `git commit --amend -m "new message"`. Otherwise use `git commit --amend --no-edit` to keep the existing message.164165## Step 8: Confirm and Commit166167### If `--quick` flag is present:168- Skip the confirmation prompt169- Auto-detect the type, generate the message, stage, and commit immediately170- Still enforce safety scans (Step 5) and branch protection (Step 2)171- Still validate the commit message (Step 7)172- Show the post-commit summary (Step 9)173174### Standard flow:175Present a summary to the user:176177```178Branch: <branch-name>179Staged: <number> file(s)180Message: <proposed commit message>181182Files:183 - path/to/file1.ts184 - path/to/file2.ts185```186187- Wait for the user to approve, edit the message, or cancel.188- **Never** append a `Co-Authored-By` or `Co-authored-by` trailer to the commit message.189- Execute the commit using a heredoc for proper formatting:190 ```191 git commit -m "$(cat <<'EOF'192 <type>(<scope>): <description>193194 <optional body>195196 <optional footers>197 EOF198 )"199 ```200- Verify with `git log --oneline -1`.201202## Step 9: Post-commit Summary203204After a successful commit, show:205206```207Committed: <short-hash> <commit message>208Branch: <branch-name>209Files: <count> changed210```211212Then suggest: "Run `git push` to push your changes." — but **do not execute `git push`**.213214## Step 10: Multi-commit Workflow215216When the user requests splitting changes into multiple commits (e.g., "commit these separately", "split into logical commits"):2172181. **Group files by change type** — separate features from fixes from refactors from docs2192. **Present the proposed grouping** to the user:220 ```221 Commit 1 (feat): path/to/new-feature.ts, path/to/component.tsx222 Commit 2 (fix): path/to/bugfix.ts223 Commit 3 (docs): README.md224 ```2253. Let the user adjust groupings before proceeding2264. **Execute sequentially** — stage and commit each group one at a time2275. **Show combined summary** at the end:228 ```229 Created 3 commits:230 abc1234 feat(ui): add user profile component231 def5678 fix(api): handle null response in auth232 ghi9012 docs: update API reference233 ```234235## Edge Cases236237- **Only staged changes**: Skip staging, commit what's already staged.238- **Mixed staged/unstaged**: Ask the user whether to include unstaged changes.239- **Merge conflicts**: If `git status` shows merge conflicts, tell the user to resolve them first.240- **Untracked files only**: Ask the user which files to add.241- **Detached HEAD**: Warn and ask for instructions before committing.242- **Empty diff after staging**: If staged changes result in no diff (e.g., only whitespace), warn the user.