branch
>
Works with
--- name: branch description: > license: MIT --- <!-- generated by scripts/build.mjs from shared/git-flow/ — edit the source there, then run: npm run build --> Run stages **0 → 1 → 5**, all of them below. **Skip stages 2, 3 and 4** — never commit, never push, never open a pull request. Uncommitted work stays uncommitted, on the new branch. Stage 0 still resolves `<remote>` and `<base>`, and skips the `gh` / `az` check. **The working tree is not touched** — staged stays staged, modified stays modified, and `git switch --create` carries both onto the new branch. Say so, and offer `branch-commit` if the user meant to commit as well. Arguments the user may pass: a branch name, a type, a base branch. Honour them over the derived defaults, and never "normalise" the casing of a name you were given. ## How this skill runs Stages: **0 preflight → 1 branch → 2 commit → 3 push → 4 pull request → 5 report**. Only the ones this skill runs appear below; run them in order and stop at the last. **Each block below is one tool call** — its lines run in one shell and answer at once, so don't split a block across calls and don't add a call a block already covers. A stage is one block unless it says otherwise: every line in a block runs before you see any of the output, so a stage whose next step depends on the previous one having worked says so and spends the second call. ## Stage 0 — Preflight (always) ```bash git rev-parse --show-toplevel git status --porcelain=v1 --branch git symbolic-ref --quiet --short HEAD git log --oneline -5 git diff --stat git diff --staged --stat ``` An unborn HEAD makes `git log` fail: report `no commits yet` and carry on, a valid state for a commit skill. Read out of that one answer: | Fact | From | |---|---| | repo root, current branch | lines 1 and 3 | | dirty / staged | porcelain lines other than the `##` header; staged = first column not space or `?` | | what changed | the two `--stat` lines — enough to name a branch and write a message | **Command discipline.** Keep output scoped — `--stat`, `--quiet`, `--porcelain`, `--query … -o tsv` — and never run a command whose full output you won't read. Every line must run in Bash *and* PowerShell: one command per line, no `\` continuation (a PowerShell parse error), no backtick (breaks Bash), and no nested quotes inside `--query` (PowerShell strips the inner pair, so any hyphenated JMESPath key is unwritable — pick a query that doesn't need one). Where no portable form exists, both variants are given. ## Stage 0 — the remote half These lines belong in the **same call** as the six above; this skill reaches a remote, so it needs `<remote>` and `<base>` before any later stage runs. ```bash git remote get-url origin | sed -E 's#(://)[^@/]+@#\1#' git symbolic-ref --quiet refs/remotes/origin/HEAD git fetch origin --quiet grep -nisE "base branch|pull request.*(target|into|against)" CLAUDE.md AGENTS.md CONTRIBUTING.md ``` PowerShell, for the two lines with no portable form: ```powershell (git remote get-url origin) -replace '://[^@/]+@','://' Select-String -Path CLAUDE.md,AGENTS.md,CONTRIBUTING.md -Pattern "base branch","pull request.*(target|into|against)" -ErrorAction SilentlyContinue ``` That strips any user-info from the URL, so what prints is safe to keep and to report. **Never print `git remote -v`** — it shows every URL unredacted, passwords and PATs included. `grep -s` matters: without it, the three convention files not existing is three warning lines in most repos. This fetch serves the branch, commit, push and pull request stages — none of them fetches again. What the extra lines give you: | Fact | From | |---|---| | platform, `<remote>` | the redacted URL: `github.com` → GitHub + `gh`; `dev.azure.com`, `.visualstudio.com`, `ssh.dev.azure.com` → Azure DevOps + `az repos`; neither → unknown, so no automated pull request, though `<remote>` still stands | | `<base>` | the convention grep wins outright; otherwise `refs/remotes/origin/HEAD` minus its prefix | **`<remote>` is `origin` unless `origin` is missing.** If it is, list names only with `git remote` and capture one redacted URL each: a single remote wins, otherwise the one GitHub or Azure DevOps remote, saying why. No remote at all stops any stage needing one. Substitute the resolved name into every later command — never hardcode `origin` past this point. **`<base>` is never guessed from a hardcoded list.** A convention in `CLAUDE.md`, `AGENTS.md` or `CONTRIBUTING.md` outranks the platform default. If neither the grep nor `refs/remotes/<remote>/HEAD` answers, ask the platform once — `gh repo view --json defaultBranchRef --jq .defaultBranchRef.name`, or for Azure DevOps, one line, stripping `refs/heads/` from the answer: ```bash az repos show --organization "https://dev.azure.com/<org>" --project "<project>" --repository "<repo>" --query defaultBranch -o tsv ``` Cache it with `git remote set-head <remote> <branch>` so later runs skip the call. Only if all that fails, take whichever of `<remote>/main`, `<remote>/master`, `<remote>/development`, `<remote>/develop` exists — and if two candidates remain plausible, take the one this ladder ranks higher and say which and why rather than asking. Branch names are case-sensitive, may contain `/` and are never re-cased: quote them. Every later stage uses `<base>`, never a literal branch name. ## Hard guardrails Refuse and explain rather than working around any of these: - **Nothing to commit** — a skill running stage 2 stops on a clean tree. For a skill that doesn't commit, a clean tree is normal; its equivalent is *nothing to ship*, in stage 4. - **No `--force`, no `--force-with-lease`, no `--no-verify`**, and no push to a protected or default branch unless the user asks for it in this turn. - **No amend, no rebase, no reset** of existing commits. New commits only. - **No `git add .` and no `git add -A`.** Stage named paths from the porcelain listing. Never stage `.env*`, `*.pem`, `*.key`, `*.pfx`, `id_rsa*`, `*.p12`, `secrets.*`, `appsettings.*.local.json`, `*.publishsettings`, a credential or token file, or anything whose diff carries an obvious live secret — flag it and leave it unstaged. - **Merge, rebase, cherry-pick, revert, bisect or sequencer operation in progress, or detached HEAD** — stop, report the state, let the user resolve it. ## Act, don't ask Preflight has already answered most of what a stage below might otherwise stop to ask about. Where it has, **make the call and name it in the report** rather than putting the question to the user — each stage says which choice is its own. The guardrails above are the exception: those stop the flow. ## Stage 1 — Branch Name format **`<type>/<short-slug>`**. `<type>` comes from `feat` `fix` `chore` `refactor` `perf` `docs` `test` `build` `ci` `style` `revert` and must match the commit's type. `<slug>` is lowercase kebab-case describing what the change does — 2-4 words, 40 chars or fewer in total, no ticket numbers unless the user gives one, no dates, no author name. Examples: `feat/add-cache-retry`, `fix/null-ref-login`, `chore/bump-serilog`. Preflight's two stats name the change in almost every case. Where they don't, read the one path that matters with `git diff -- <path>` — never the whole tree. **A clean tree has no diff to name a branch from**: take the name the user passed, and if there is none, ask for one rather than inventing a slug for work that doesn't exist yet. One call — preflight already fetched, so this creates and nothing else: ```bash git switch --create <type>/<slug> <remote>/<base> ``` - **A dirty tree branches off HEAD instead**, so the pending work comes along: `git switch --create <type>/<slug>`. That case spends one call first, because branching off a HEAD that already carries commits the base lacks would pull them silently into the new branch and a later pull request — `git rev-list --left-right --count <remote>/<base>...HEAD`, and if the right side isn't `0`, stop and ask rather than creating. Say which of the two forms you used. - **The name is already taken** — the create fails and says so. Append `-2`, `-3`, … or pick a better slug in one more call. Don't probe for collisions first: the create *is* the probe. - Already on a feature branch that holds this work → **reuse it** instead of stacking a second one, and report its upstream and its commits relative to `<base>`. That is a call to make, not a question to ask. ## Stage 5 — Report One compact block, no prose padding. Omit the lines for stages this skill doesn't run; a stage that was skipped or failed keeps its line and carries the reason. ``` platform GitHub | Azure DevOps branch feat/add-cache-retry (from main) commit a1b2c3d feat(cache): add retry on transient Redis failure push <remote>/feat/add-cache-retry pr https://github.com/owner/repo/pull/42 ``` A commit-only skill may keep the `branch` line as context, naming where the commit landed. Stage 2 split the work into several commits, so one `commit` line each, oldest first: ``` branch fix/tidy-cache-layer (from main) commit a1b2c3d fix(cache): guard against a null connection commit e4f5a6b refactor(cache): extract the key builder ```
More Git Workflows skills
git-commit
github/awesome-copilot
Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions "/commit". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping
git-workflow-and-versioning
addyosmani/agent-skills
Structures git workflow practices. Use when making any code change. Use when committing, branching, resolving conflicts, or when you need to organize work across multiple parallel streams. Use when cutting a release, choosing a semantic version bump, tagging, or writing a changelog.
resolve-merge-conflicts
warpdotdev/common-skills
Resolve Git merge conflicts by extracting only unresolved paths, conflict hunks, and compact diffs instead of loading whole files into context. Use when a merge, rebase, cherry-pick, or stash pop stops on conflicts, when `git status` shows unmerged paths, or when files contain conflict markers.

