Submit Changes
This skill automates the full pipeline from local changes to an open pull request: branch → commit → push → PR. Each phase is idempotent — already-completed steps are skipped automatically.
When to Use This Skill
- Submitting local changes as a complete workflow in one step
- Automating the branch + commit + PR process without manual intervention
- Shipping finished work without manually running each git command
Safety Rules
These rules are non-negotiable:
- NEVER run destructive commands (
git reset, git clean, git checkout -- ., git push --force, git rebase)
- NEVER bypass hooks with
--no-verify
- NEVER disable signing with
--no-gpg-sign
- NEVER auto-fix pre-commit failures — report the failure and stop
- On any failure: report the error and stop immediately
Automatic Change Analysis
Before executing any phases, analyze the working tree and staged changes:
git status --porcelain
git diff HEAD
From the diff, automatically determine:
- Type — From the allowed types (see commit-code skill)
- Scope — From the allowed scopes (see commit-code skill)
- Gitmoji — Best-fit emoji for the type and intent (see commit-code skill)
- Subject — Concise imperative phrase, lowercase, no period, under 70 chars
These values drive the branch name, commit message, and PR title throughout all phases.
Phase 1 — Branch
Check current branch: git rev-parse --abbrev-ref HEAD
If on main, create and switch to a new branch following checkout-branch conventions:
git checkout -b <type>/<scope>-<description>
Validate branch-name conformance for the current branch:
pnpm exec validate-branch-name -t "<branch>"
If validation fails, run the rename-branch skill to derive and apply a compliant branch name, then re-run validation.
Push to remote and set upstream:
git push --set-upstream origin <branch>
Branch name format: <type>/<scope>-<description> (kebab-case, 2–4 keyword description)
Phase 2 — Stage, Commit & Push
Skip if: Working tree is clean (git status --porcelain returns nothing).
Stage all changes:
git add -A
Compose commit message: <type>(<scope>): <gitmoji> <subject> — single line, max 128 chars, no body/footer
Commit with signing enabled:
export GPG_TTY="$(tty)"
git commit -S -m "<type>(<scope>): <gitmoji> <subject>"
Verify the new commit signature:
git verify-commit HEAD
✅ Best practice: Let Husky run signing checks automatically. The pre-commit hook runs check-commit-signing-configuration.sh, and the pre-push hook runs check-push-commit-signatures.sh.
⚠️ Warning: Do not invoke scripts/git/check-push-commit-signatures.sh directly during normal submits. It is designed for hook stdin input and can block or fail when run without ref-update data.
If pre-commit hooks fail
Stop immediately. Report the hook output so the user can see what failed. Do NOT apply fixes or proceed to push.
If commit succeeds
Push to remote:
git push --set-upstream origin <branch>
Phase 3 — Pull Request
Skip if: A PR already exists for the current branch:
gh pr list --head <branch> --state open
Title: Same format as the commit message — <type>(<scope>): <gitmoji> <subject>
Body: Auto-generate from the diff using the PR template structure:
- 🌰 Summary: Overall purpose in 1-2 sentences
- 📝 Details: Bulleted list of meaningful changes
- 🧪 Testing: Relevant
nx run <project>:<target> commands and manual steps
- 🔗 Related: Issue links discovered from branch name, commits, or
gh issue list --search
Assignee and labels — Validate Conventions rejects a pull request whose metadata disagrees with its title, so set all of this at creation time rather than waiting for the reconciliation step to backfill it:
- Assignee:
--assignee @me. A pull request with no assignee fails validation.
- Type label: Exactly one
type:* label, matching the title's type. Never more than one, never a mismatch.
- Scope label(s): One
scope:* label per scope named in the title — if the title carries more than one scope (type(scope-one,scope-two): …), add a --label scope:<name> for each of them, and no extra scope:* label beyond what the title names.
- Source label: Exactly one
source:* label. This skill is agent-driven, so use source:agent — never source:human, and never both.
- Never apply
do-not-merge — it blocks the pull request while present, and this workflow is opening one for immediate review, not staging a draft.
Create the PR:
gh pr create \
--title "<type>(<scope>): <gitmoji> <subject>" \
--body "<generated body>" \
--base main \
--assignee @me \
--label type:<type> \
--label scope:<scope> \
--label source:agent
Repeat --label scope:<name> for each additional scope the title names.
Confirm the metadata actually landed — a label GitHub silently drops (typo, not-yet-created) fails CI just as surely as never adding it:
gh pr view <branch> --json number,labels,assignees
If any expected label or the assignee is missing, add it with gh pr edit <number> --add-label <label> / --add-assignee @me rather than leaving it to Validate Conventions to catch and fail on.
For complete PR conventions and description guidelines, see create-pull-request skill. For the full label vocabulary, the opened/reopened reconciliation step that creates missing labels, and how to fix each individual metadata failure, see the triage-deployment skill.
Output
After completing all phases, print a summary table:
| Phase |
Result |
| Branch |
Created <branch> / Already on <branch> |
| Commit |
<type>(<scope>): <gitmoji> <subject> / Skipped (clean) |
| PR |
Created <url> / Already exists <url> |
| Labels |
type:*, scope:* (one per title scope), source:agent |
| Assignee |
@me — confirmed via gh pr view |
Resources
1---2name: submit-changes3description: Automatically submit local changes through the full branch → commit → push → pull request pipeline. Includes branch-name conformance checks and automatic branch rename when needed. Use this skill when asked to submit, ship, or push changes; when you want to move from local changes to an open PR in one step; or when orchestrating the complete git workflow automatically without manual steps.4license: MIT5---6
7# Submit Changes
8
9This skill automates the full pipeline from local changes to an open pull request: **branch → commit → push → PR**. Each phase is idempotent — already-completed steps are skipped automatically.
10
11## When to Use This Skill
12
13- Submitting local changes as a complete workflow in one step
14- Automating the branch + commit + PR process without manual intervention
15- Shipping finished work without manually running each git command
16
17## Safety Rules
18
19These rules are non-negotiable:
20
21- **NEVER** run destructive commands (`git reset`, `git clean`, `git checkout -- .`, `git push --force`, `git rebase`)
22- **NEVER** bypass hooks with `--no-verify`
23- **NEVER** disable signing with `--no-gpg-sign`
24- **NEVER** auto-fix pre-commit failures — report the failure and stop
25- On any failure: **report the error and stop immediately**
26
27## Automatic Change Analysis
28
29Before executing any phases, analyze the working tree and staged changes:
30
31```bash
32git status --porcelain
33git diff HEAD
34```
35
36From the diff, automatically determine:
37
381. **Type** — From the allowed types (see [commit-code skill](../commit-code/SKILL.md))
392. **Scope** — From the allowed scopes (see [commit-code skill](../commit-code/SKILL.md))
403. **Gitmoji** — Best-fit emoji for the type and intent (see [commit-code skill](../commit-code/SKILL.md))
414. **Subject** — Concise imperative phrase, lowercase, no period, under 70 chars
42
43These values drive the branch name, commit message, and PR title throughout all phases.
44
45## Phase 1 — Branch
46
471. Check current branch: `git rev-parse --abbrev-ref HEAD`
482. If on `main`, create and switch to a new branch following [checkout-branch conventions](../checkout-branch/SKILL.md):
49
50 ```bash
51 git checkout -b <type>/<scope>-<description>
52 ```
53
543. Validate branch-name conformance for the current branch:
55
56 ```bash
57 pnpm exec validate-branch-name -t "<branch>"
58 ```
59
604. If validation fails, run the [rename-branch skill](../rename-branch/SKILL.md) to derive and apply a compliant branch name, then re-run validation.
615. Push to remote and set upstream:
62
63 ```bash
64 git push --set-upstream origin <branch>
65 ```
66
67Branch name format: `<type>/<scope>-<description>` (kebab-case, 2–4 keyword description)
68
69## Phase 2 — Stage, Commit & Push
70
71**Skip if:** Working tree is clean (`git status --porcelain` returns nothing).
72
731. Stage all changes:
74
75 ```bash
76 git add -A
77 ```
78
792. Compose commit message: `<type>(<scope>): <gitmoji> <subject>` — single line, max 128 chars, no body/footer
80
813. Commit with signing enabled:
82
83 ```bash
84 export GPG_TTY="$(tty)"
85 git commit -S -m "<type>(<scope>): <gitmoji> <subject>"
86 ```
87
884. Verify the new commit signature:
89
90 ```bash
91 git verify-commit HEAD
92 ```
93
94> ✅ **Best practice:** Let Husky run signing checks automatically. The pre-commit hook runs `check-commit-signing-configuration.sh`, and the pre-push hook runs `check-push-commit-signatures.sh`.
95>
96> ⚠️ **Warning:** Do not invoke `scripts/git/check-push-commit-signatures.sh` directly during normal submits. It is designed for hook stdin input and can block or fail when run without ref-update data.
97
98### If pre-commit hooks fail
99
100**Stop immediately.** Report the hook output so the user can see what failed. Do **NOT** apply fixes or proceed to push.
101
102### If commit succeeds
103
104Push to remote:
105
106```bash
107git push --set-upstream origin <branch>
108```
109
110## Phase 3 — Pull Request
111
112**Skip if:** A PR already exists for the current branch:
113
114```bash
115gh pr list --head <branch> --state open
116```
117
1181. Title: Same format as the commit message — `<type>(<scope>): <gitmoji> <subject>`
1192. Body: Auto-generate from the diff using the PR template structure:
120 - **🌰 Summary**: Overall purpose in 1-2 sentences
121 - **📝 Details**: Bulleted list of meaningful changes
122 - **🧪 Testing**: Relevant `nx run <project>:<target>` commands and manual steps
123 - **🔗 Related**: Issue links discovered from branch name, commits, or `gh issue list --search`
1243. Assignee and labels — Validate Conventions rejects a pull request whose metadata disagrees with its title, so set all of this at creation time rather than waiting for the reconciliation step to backfill it:
125 - **Assignee**: `--assignee @me`. A pull request with no assignee fails validation.
126 - **Type label**: Exactly one `type:*` label, matching the title's type. Never more than one, never a mismatch.
127 - **Scope label(s)**: One `scope:*` label per scope named in the title — if the title carries more than one scope (`type(scope-one,scope-two): …`), add a `--label scope:<name>` for each of them, and no extra `scope:*` label beyond what the title names.
128 - **Source label**: Exactly one `source:*` label. This skill is agent-driven, so use `source:agent` — never `source:human`, and never both.
129 - **Never** apply `do-not-merge` — it blocks the pull request while present, and this workflow is opening one for immediate review, not staging a draft.
1304. Create the PR:
131
132 ```bash
133 gh pr create \
134 --title "<type>(<scope>): <gitmoji> <subject>" \
135 --body "<generated body>" \
136 --base main \
137 --assignee @me \
138 --label type:<type> \
139 --label scope:<scope> \
140 --label source:agent
141 ```
142
143 Repeat `--label scope:<name>` for each additional scope the title names.
144
1455. Confirm the metadata actually landed — a label GitHub silently drops (typo, not-yet-created) fails CI just as surely as never adding it:
146
147 ```bash
148 gh pr view <branch> --json number,labels,assignees
149 ```
150
151 If any expected label or the assignee is missing, add it with `gh pr edit <number> --add-label <label>` / `--add-assignee @me` rather than leaving it to Validate Conventions to catch and fail on.
152
153For complete PR conventions and description guidelines, see [create-pull-request skill](../create-pull-request/SKILL.md). For the full label vocabulary, the `opened`/`reopened` reconciliation step that creates missing labels, and how to fix each individual metadata failure, see the [triage-deployment skill](../triage-deployment/SKILL.md).
154
155## Output
156
157After completing all phases, print a summary table:
158
159| Phase | Result |
160|----------|-----------------------------------------------------------|
161| Branch | Created `<branch>` / Already on `<branch>` |
162| Commit | `<type>(<scope>): <gitmoji> <subject>` / Skipped (clean) |
163| PR | Created `<url>` / Already exists `<url>` |
164| Labels | `type:*`, `scope:*` (one per title scope), `source:agent` |
165| Assignee | `@me` — confirmed via `gh pr view` |
166
167## Resources
168
169- [checkout-branch skill](../checkout-branch/SKILL.md) — Branch naming conventions
170- [rename-branch skill](../rename-branch/SKILL.md) — Rename non-conforming branches before commit/push
171- [commit-code skill](../commit-code/SKILL.md) — Commit message format, types, scopes, gitmoji
172- [create-pull-request skill](../create-pull-request/SKILL.md) — PR conventions and description template, full Labels section
173- [triage-deployment skill](../triage-deployment/SKILL.md) — Label vocabulary, `opened`/`reopened` reconciliation, fixing metadata failures
174- [check-commit-signing-configuration.sh](../../../scripts/git/check-commit-signing-configuration.sh) — Pre-commit hook signing prerequisite check
175- [check-push-commit-signatures.sh](../../../scripts/git/check-push-commit-signatures.sh) — Pre-push hook commit signature validation