PR
Context
- Current branch: !
git rev-parse --abbrev-ref HEAD - Git status: !
git status -b --porcelain - Worktrees: !
git worktree list - Default branch: !
gh repo view --json defaultBranchRef --jq .defaultBranchRef.name - Compare ref: !
git rev-parse --abbrev-ref origin/HEAD - Commits ahead: !
git log --oneline origin/HEAD..HEAD
Skip Gate
Every probe above ran in the session's working directory, so each one describes Current branch. The branch holding the work the user asked to ship is <branch> throughout this document. When it is not Current branch, re-derive these before reading further and use the re-derived values everywhere below: its checkout path from Worktrees, Commits ahead from git log --oneline origin/HEAD..<branch>, and Git status from git -C <path> status -b --porcelain. Status is the one probe a branch name cannot stand in for.
Stop and tell the user, without working around it, when:
Default branchorCompare refis empty or errored: never guess a branch name or substitute another refCompare refis notorigin/<Default branch>: they needgit remote set-head origin --auto- neither
Worktreesnorgit branch --list <branch>reports it: name the mismatch and stop rather than shipping whatever this directory happens to be on Commits aheadis empty: nothing to ship<branch>isDefault branch: a PR needs a branch of its own- a subject in
Commits aheadstarts withwip,fixup!, orsquash!: they needgit rebase -i; do not auto-rebase
If Git status lists an uncommitted change, name the files and ask whether to proceed.
Editing a PR the user named by number or URL ships nothing, so skip this gate and step 1, and pass that number where step 2 takes <branch>.
Title
Follow .gitmessage / CONTRIBUTING.md when the repo has one, else Conventional Commits.
Issue Link
Collect every issue number from both sources: the branch prefix #<number>_..., and closes #N / fixes #N / refs #N (case-insensitive) in commit bodies ahead of Compare ref. Write one closes #N line per distinct issue, the branch prefix's first. With none found, omit the line.
Body
Never write the description, not even a draft. The author writes it before marking ready; an agent-written one hands the reviewer a restated diff instead of the author's context.
closes #<number>
---
<body>
<body> is the repo's PR template (any of GitHub's conventional locations) verbatim and unfilled, else empty. Without an issue link, drop that line and the ---; an empty body is still passed as --body "".
Steps
- Push by name:
git push -u origin <branch>.gh pr createonly prompts for this (fails without a TTY) andgh pr editnever checks, so unpushed commits would be missing from the PR - Open PR exists (
gh pr view <branch> --json body) →gh pr edit <branch> --title .... Pass--bodyonly to prepend an issue link the body lacks, keeping the author's text unchanged - Otherwise →
gh pr create --draft --title ... --body ... --base <base> --head <branch> --assignee @me. Always draft; the author marks ready for review<base>:$ARGUMENTSwhengit rev-parse --verify -q "$ARGUMENTS"orgit rev-parse --verify -q "origin/$ARGUMENTS"succeeds, elseDefault branch. Never anorigin/-prefixed ref, since--basetakes a branch name--head <branch>: always explicit. Left out,gh pr createinfers head from the session's working directory