branch

>

nicotinez/skills6 installsMITSynced Aug 22

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
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

← All Git Workflows skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY