GitHub Pull Request Creation
Check whether a pull request already exists for the current branch. Create one
if it does not, and keep its body up to date with the commits on the branch.
The body is built one of two ways, depending on whether the repository defines a
pull request template:
- Template mode — a
.github/PULL_REQUEST_TEMPLATE.md file exists. The PR
body is built from that template (see Template Mode).
- Commit mode — no template file exists. The PR body is built from the
branch's commit messages (see Commit Mode).
Template Mode
When .github/PULL_REQUEST_TEMPLATE.md exists, use it as the source of the PR
body:
- Start from the exact contents of the template file. Keep its headings,
section order, comments, and checklist items intact.
- Fill in the template's sections using information derived from the branch's
commits — e.g. write the summary/description from the commit subjects and
bodies, and tick any checklist items that the commits clearly satisfy. Do not
paste the raw commit log in place of the template; preserve the template's
structure.
- For sections you cannot confidently fill from the commits, ask the user for
the missing information and use their answer to complete the section. If the
user does not provide it, leave the section as it is in the template (keep the
placeholder text or empty checkboxes) so the author can complete it later.
- When updating an existing PR, refresh only the parts derived from commits
(e.g. the description) so they reflect every commit on the branch. Preserve
any content a human already filled into other sections; do not overwrite the
whole body back to the blank template.
Commit Mode
When no template file exists, the pull request body is built from all
commits on the branch. Each commit contributes its full message (subject line,
blank line, body), and commits are separated from one another by blank lines, in
chronological order (oldest first):
subject of commit 1
body of commit 1
subject of commit 2
body of commit 2
The body must be built from the exact bytes of each commit message,
including the 72-character wrapping. Do not re-flow, unwrap, or re-format the
text. Always pipe it into --body-file - (inline --body "..." risks stripping
or normalizing the hard line breaks).
Steps
Determine the base branch:
base="$(gh pr view --json baseRefName --jq .baseRefName 2>/dev/null \
|| git remote show origin | sed -n 's/.*HEAD branch: //p')"
Build the body into a temporary file, choosing the mode by whether a template
exists:
Template mode (.github/PULL_REQUEST_TEMPLATE.md exists): start from
the template and fill its sections from the branch commits, as described in
Template Mode. Use the commits for reference:
git log --reverse --format='%B%n' "origin/$base..HEAD"
Commit mode (no template): build the body from the raw commit messages.
%B is a commit's raw message (subject + blank line + body), and the
trailing %n%n separates consecutive commits with a blank line:
git log --reverse --format='%B%n' "origin/$base..HEAD"
Check for an existing pull request:
gh pr view --json url
If no pull request exists (the command above fails), ask the user whether
one should be created. Only continue if the user confirms. Create it as a
draft, using the first commit's subject as the title and the body built
in step 2 (pipe the body in via --body-file -):
title="$(git log --reverse --format='%s' "origin/$base..HEAD" | head -n1)"
# <body-source> is the template-filled body or the commit log, per step 2.
<body-source> | gh pr create --draft --title "$title" --body-file -
If a pull request already exists, refresh its body:
In commit mode, regenerate the body so it includes every commit on the
branch (this matters when the branch has more than one commit, or after
adding commits to an existing pull request):
git log --reverse --format='%B%n' "origin/$base..HEAD" | gh pr edit --body-file -
In template mode, refresh only the commit-derived sections of the
existing body and preserve everything the author already filled in, then
update it:
# <updated-body> keeps the template structure and human-authored content,
# refreshing only the commit-derived sections.
<updated-body> | gh pr edit --body-file -
Leave the title unchanged unless the first commit's subject changed. If a
single commit has no body, its contribution is just the subject line.
1---2name: github-pr-create3description: Create or update the pull request for the current branch. Creates a draft PR titled from the first commit's subject. If a `.github/PULL_REQUEST_TEMPLATE.md` exists it fills that template, otherwise it keeps the PR body in sync with the exact commit messages on the branch. Use after committing, or when asked to "create a PR", "open a pull request", or "update the PR body/description".4---56# GitHub Pull Request Creation78Check whether a pull request already exists for the current branch. Create one9if it does not, and keep its body up to date with the commits on the branch.1011The body is built one of two ways, depending on whether the repository defines a12pull request template:1314- **Template mode** — a `.github/PULL_REQUEST_TEMPLATE.md` file exists. The PR15 body is built from that template (see [Template Mode](#template-mode)).16- **Commit mode** — no template file exists. The PR body is built from the17 branch's commit messages (see [Commit Mode](#commit-mode)).1819## Template Mode2021When `.github/PULL_REQUEST_TEMPLATE.md` exists, use it as the source of the PR22body:2324- Start from the **exact contents** of the template file. Keep its headings,25 section order, comments, and checklist items intact.26- Fill in the template's sections using information derived from the branch's27 commits — e.g. write the summary/description from the commit subjects and28 bodies, and tick any checklist items that the commits clearly satisfy. Do not29 paste the raw commit log in place of the template; preserve the template's30 structure.31- For sections you cannot confidently fill from the commits, ask the user for32 the missing information and use their answer to complete the section. If the33 user does not provide it, leave the section as it is in the template (keep the34 placeholder text or empty checkboxes) so the author can complete it later.35- When **updating** an existing PR, refresh only the parts derived from commits36 (e.g. the description) so they reflect every commit on the branch. Preserve37 any content a human already filled into other sections; do not overwrite the38 whole body back to the blank template.3940## Commit Mode4142When no template file exists, the pull request body is built from **all**43commits on the branch. Each commit contributes its full message (subject line,44blank line, body), and commits are separated from one another by blank lines, in45chronological order (oldest first):4647```48subject of commit 14950body of commit 1515253subject of commit 25455body of commit 256```5758The body must be built from the **exact bytes** of each commit message,59including the 72-character wrapping. Do not re-flow, unwrap, or re-format the60text. Always pipe it into `--body-file -` (inline `--body "..."` risks stripping61or normalizing the hard line breaks).6263## Steps64651. Determine the base branch:6667 ```sh68 base="$(gh pr view --json baseRefName --jq .baseRefName 2>/dev/null \69 || git remote show origin | sed -n 's/.*HEAD branch: //p')"70 ```71722. Build the body into a temporary file, choosing the mode by whether a template73 exists:74 - **Template mode** (`.github/PULL_REQUEST_TEMPLATE.md` exists): start from75 the template and fill its sections from the branch commits, as described in76 [Template Mode](#template-mode). Use the commits for reference:7778 ```sh79 git log --reverse --format='%B%n' "origin/$base..HEAD"80 ```8182 - **Commit mode** (no template): build the body from the raw commit messages.83 `%B` is a commit's raw message (subject + blank line + body), and the84 trailing `%n%n` separates consecutive commits with a blank line:8586 ```sh87 git log --reverse --format='%B%n' "origin/$base..HEAD"88 ```89903. Check for an existing pull request:9192 ```sh93 gh pr view --json url94 ```95964. If **no** pull request exists (the command above fails), ask the user whether97 one should be created. Only continue if the user confirms. Create it as a98 **draft**, using the first commit's subject as the title and the body built99 in step 2 (pipe the body in via `--body-file -`):100101 ```sh102 title="$(git log --reverse --format='%s' "origin/$base..HEAD" | head -n1)"103 # <body-source> is the template-filled body or the commit log, per step 2.104 <body-source> | gh pr create --draft --title "$title" --body-file -105 ```1061075. If a pull request **already** exists, refresh its body:108 - In **commit mode**, regenerate the body so it includes every commit on the109 branch (this matters when the branch has more than one commit, or after110 adding commits to an existing pull request):111112 ```sh113 git log --reverse --format='%B%n' "origin/$base..HEAD" | gh pr edit --body-file -114 ```115116 - In **template mode**, refresh only the commit-derived sections of the117 existing body and preserve everything the author already filled in, then118 update it:119120 ```sh121 # <updated-body> keeps the template structure and human-authored content,122 # refreshing only the commit-derived sections.123 <updated-body> | gh pr edit --body-file -124 ```125126 Leave the title unchanged unless the first commit's subject changed. If a127 single commit has no body, its contribution is just the subject line.