git-workflow
One skill, all git ops. Configurable via CLAUDE.local.md.
Step 0: read project conventions
Before any operation, read CLAUDE.local.md (repo root) if it exists. Look for a ## Git conventions block. Use those values to override the defaults below. Examples of overridable values: commit format, default branch, branch naming, Co-Authored-By inclusion, PR title format.
If no CLAUDE.local.md or no ## Git conventions block, use the defaults documented in each section.
Operations
commit
Defaults:
- Format:
[TICKET-XXX] type: description if current branch matches ^[A-Z]+-\d+, else type: description
- Subject follows Conventional Commits (
feat/fix/refactor/docs/test/chore/perf/ci/build/style/revert)
- Subject: imperative, lowercase, no period, ≤72 chars
- Body: explain what + why for non-trivial changes; skip for trivial
- NO
Co-Authored-By trailer
- NO "Generated with Claude Code" or any attribution footer
- One logical change per commit — when session work spans multiple concerns, split
Workflow:
git status --short — see all changes
- Classify files: session work (created/edited this conversation) vs pre-existing
- Stage session work by name:
git add path1 path2. Never git add . or git add -A unless explicitly asked
- Sensitive files (
.env, credentials, API keys): warn and exclude
git diff --staged — review
- Extract ticket key from branch name:
git branch --show-current | grep -oE '^[A-Z]+-[0-9]+'
- Generate subject. If ticket key found, prefix
[KEY]
- Commit via heredoc:
git commit -m "$(cat <<'EOF'
[XYZ-123] type: imperative subject
Optional body. What changed and why.
EOF
)"
git log --oneline -1 — confirm
push
Defaults:
- Plain
git push for regular branches
- Block
--force (handled by .claude/hooks/block-dangerous-git.sh if installed; otherwise warn and refuse)
- Block push to
main/master/develop without explicit confirmation
Workflow:
- Check current branch:
git branch --show-current
- If branch is
main/master/develop, ask for explicit confirmation
- Check upstream:
git rev-parse --abbrev-ref @{u} 2>/dev/null
- If no upstream,
git push -u origin "$(git branch --show-current)". Else git push
- Report result
PR (open PR, create pull request)
Defaults:
- Title: same format as commit subject (
[TICKET-XXX] type: description)
- Body: summary + test plan from commits since base branch
- NO "Generated with Claude Code" footer
- Created via
gh pr create — never the web UI
Workflow:
- Push branch first if not pushed (see push section)
- Determine base branch (default from CLAUDE.local.md or
git symbolic-ref --short refs/remotes/origin/HEAD)
- Generate body:
## Summary
- <bullet from each commit>
## Test plan
- [ ] <test item>
- [ ] <test item>
- Title format:
[KEY] type: description if ticket present in branch, else type: description
- Create:
gh pr create --title "..." --body "$(cat <<'EOF'
## Summary
...
## Test plan
...
EOF
)"
- Print PR URL
sync (sync with main, rebase)
Defaults:
- Rebase, not merge
- Refuse if working tree dirty — ask user to commit or stash
Workflow:
git fetch origin
git rebase origin/<default-branch>
If conflicts: report them, do NOT auto-resolve, let user decide.
branch (new branch, switch branch)
Defaults:
- Use
git switch -c (not git checkout -b)
- Branch name: prompt for ticket key + slug if not provided
Workflow:
git switch -c <ticket>-<slug>
# or
git switch -c <ticket>/<slug>
stash (stash my work)
Defaults:
- Always with a message:
git stash push -m "..."
- Never bare
git stash
Workflow:
git stash push -m "<short description of what's being saved>"
Notes
- All defaults assume
block-dangerous-git.sh hook is installed via bootstrap-workflow. If absent, manually refuse the same patterns (force-push, hard-reset, etc.).
- If the project has a PR template at
.github/PULL_REQUEST_TEMPLATE.md, use it as the body skeleton instead of the generic summary/test-plan format above.
1---2name: git-workflow3description: Use for any git operation in this project — commit, push, PR, sync, branch, stash. Reads conventions from CLAUDE.local.md; falls back to defaults. Trigger phrases: "commit", "push", "open PR", "create pull request", "sync with main", "stash my work", "new branch".4---56# git-workflow78One skill, all git ops. Configurable via `CLAUDE.local.md`.910## Step 0: read project conventions1112Before any operation, read `CLAUDE.local.md` (repo root) if it exists. Look for a `## Git conventions` block. Use those values to override the defaults below. Examples of overridable values: commit format, default branch, branch naming, Co-Authored-By inclusion, PR title format.1314If no `CLAUDE.local.md` or no `## Git conventions` block, use the defaults documented in each section.1516## Operations1718### commit1920**Defaults:**2122- Format: `[TICKET-XXX] type: description` if current branch matches `^[A-Z]+-\d+`, else `type: description`23- Subject follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) (`feat`/`fix`/`refactor`/`docs`/`test`/`chore`/`perf`/`ci`/`build`/`style`/`revert`)24- Subject: imperative, lowercase, no period, ≤72 chars25- Body: explain what + why for non-trivial changes; skip for trivial26- **NO** `Co-Authored-By` trailer27- **NO** "Generated with Claude Code" or any attribution footer28- One logical change per commit — when session work spans multiple concerns, split2930**Workflow:**31321. `git status --short` — see all changes332. Classify files: session work (created/edited this conversation) vs pre-existing343. Stage session work by name: `git add path1 path2`. Never `git add .` or `git add -A` unless explicitly asked354. Sensitive files (`.env`, credentials, API keys): warn and exclude365. `git diff --staged` — review376. Extract ticket key from branch name: `git branch --show-current | grep -oE '^[A-Z]+-[0-9]+'`387. Generate subject. If ticket key found, prefix `[KEY] `398. Commit via heredoc:4041```bash42git commit -m "$(cat <<'EOF'43[XYZ-123] type: imperative subject4445Optional body. What changed and why.46EOF47)"48```49509. `git log --oneline -1` — confirm5152### push5354**Defaults:**5556- Plain `git push` for regular branches57- Block `--force` (handled by `.claude/hooks/block-dangerous-git.sh` if installed; otherwise warn and refuse)58- Block push to `main`/`master`/`develop` without explicit confirmation5960**Workflow:**61621. Check current branch: `git branch --show-current`632. If branch is `main`/`master`/`develop`, ask for explicit confirmation643. Check upstream: `git rev-parse --abbrev-ref @{u} 2>/dev/null`654. If no upstream, `git push -u origin "$(git branch --show-current)"`. Else `git push`665. Report result6768### PR (`open PR`, `create pull request`)6970**Defaults:**7172- Title: same format as commit subject (`[TICKET-XXX] type: description`)73- Body: summary + test plan from commits since base branch74- **NO** "Generated with Claude Code" footer75- Created via `gh pr create` — never the web UI7677**Workflow:**78791. Push branch first if not pushed (see push section)802. Determine base branch (default from CLAUDE.local.md or `git symbolic-ref --short refs/remotes/origin/HEAD`)813. Generate body:8283```markdown84## Summary8586- <bullet from each commit>8788## Test plan8990- [ ] <test item>91- [ ] <test item>92```93944. Title format: `[KEY] type: description` if ticket present in branch, else `type: description`955. Create:9697```bash98gh pr create --title "..." --body "$(cat <<'EOF'99## Summary100...101## Test plan102...103EOF104)"105```1061076. Print PR URL108109### sync (`sync with main`, `rebase`)110111**Defaults:**112113- Rebase, not merge114- Refuse if working tree dirty — ask user to commit or stash115116**Workflow:**117118```bash119git fetch origin120git rebase origin/<default-branch>121```122123If conflicts: report them, do NOT auto-resolve, let user decide.124125### branch (`new branch`, `switch branch`)126127**Defaults:**128129- Use `git switch -c` (not `git checkout -b`)130- Branch name: prompt for ticket key + slug if not provided131132**Workflow:**133134```bash135git switch -c <ticket>-<slug>136# or137git switch -c <ticket>/<slug>138```139140### stash (`stash my work`)141142**Defaults:**143144- Always with a message: `git stash push -m "..."`145- Never bare `git stash`146147**Workflow:**148149```bash150git stash push -m "<short description of what's being saved>"151```152153## Notes154155- All defaults assume `block-dangerous-git.sh` hook is installed via `bootstrap-workflow`. If absent, manually refuse the same patterns (force-push, hard-reset, etc.).156- If the project has a PR template at `.github/PULL_REQUEST_TEMPLATE.md`, use it as the body skeleton instead of the generic summary/test-plan format above.