Home / Alt manpages / gh-pr-create(1)

  • gh-pr-create(1)
  • User command
  • linux

Create a Pull Request with gh pr create

gh pr create turns a local branch into a GitHub pull request without leaving the terminal, complete with title, description and reviewers. The examples use GitHub CLI 2.87.3, reported by the installed gh binary. The Debian package database reports gh 2.45.0-1ubuntu0.3+esm3, so the binary and package metadata disagree on this machine: check gh --version on your own host before relying on a version-specific option.

Allow about fifteen minutes for a normal pull request, longer if the branch has never been pushed. You need a GitHub repository, an authenticated gh session, a local branch containing the intended commits, and permission to push its head branch. These steps create remote state, so read the final review carefully before running the creation command.

1. Check the repository and authentication

Start with ordinary, read-only checks, run from the worktree that contains the changes:

$ git status --short --branch
## feature/fix-login
$ gh auth status
github.com
  Logged in to github.com account YOUR_LOGIN
  Git operations protocol: ssh

The branch shown by git status is the default head branch for the command. A clean status is not required, but do not accidentally include uncommitted work: gh pr create builds the pull request from commits, not from a loose working-tree diff. If authentication fails, sign in through your normal approved process before continuing. Do not paste a token into a shell command or the pull request body.

Checkpoint

Identify the repository and branch you intend to publish:

$ gh repo view --json nameWithOwner,defaultBranchRef
{"defaultBranchRef":{"name":"main"},"nameWithOwner":"OWNER/REPOSITORY"}
$ git branch --show-current
feature/fix-login

2. Confirm the commits and target branch

Review the commits that will be proposed before you write a word of the pull request text:

$ git log --oneline --decorate -5
abc1234 (HEAD -> feature/fix-login) Handle expired login sessions
def5678 Add regression coverage for session expiry
$ git diff --stat main...HEAD
 src/session.go      | 18 +++++++++++++-----
 src/session_test.go | 24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 7 deletions(-)

Replace main with the real base branch when necessary. --base is optional: without it, gh uses the current branch's branch.<current>.gh-merge-base Git setting when present, otherwise the repository's default branch. That fallback is convenient but easy to miss, so pass --base when the target matters. Do not reach for sudo here: elevated privileges fix neither a wrong branch, a missing remote, nor a GitHub permission problem.

3. Prepare a complete, explicit command

For a predictable non-interactive creation, provide the title and body yourself, quoted so shell punctuation stays in the argument:

$ gh pr create \
    --base main \
    --head feature/fix-login \
    --title "Handle expired login sessions" \
    --body "Users now receive a fresh session after expiry.\n+\n+Tests: go test ./..." \
    --reviewer REVIEWER_LOGIN \
    --draft
https://github.com/OWNER/REPOSITORY/pull/123

Replace every uppercase placeholder. The printed URL is the expected success result. --draft creates a draft, useful when the branch is ready for review but not ready to merge; drop it for a normal open pull request.

The command may push the current branch if it is not fully available on a remote. It can also ask where to push and offer to fork the base repository, a meaningful remote change, not a harmless prompt. Stop if the proposed repository or branch is not the one you expect.

4. Preview before creating when a push is possible

On gh 2.87.3, --dry-run prints the details instead of creating the pull request. It may still push Git changes, so treat it as a preview of the PR operation, not a no-network test:

$ gh pr create \
    --base main \
    --head feature/fix-login \
    --title "Handle expired login sessions" \
    --body-file /path/to/review-body.txt \
    --dry-run
Would create a pull request in OWNER/REPOSITORY
...

Review the displayed base, head, title and body. If the branch must never be pushed or forked by this command, use an explicit head in the form OWNER:BRANCH and confirm the branch already exists remotely: --head also skips the automatic forking or pushing behaviour. An organisation is not supported as the user in the USER:BRANCH head syntax on this installed command.

5. Choose how the body is supplied

Use --body-file when the description is more than a short paragraph or holds Markdown that deserves its own review:

$ gh pr create \
    --base main \
    --head feature/fix-login \
    --title "Handle expired login sessions" \
    --body-file /path/to/review-body.txt
  • - as the file name reads the body from standard input.
  • --template starts from a template file.
  • --editor opens an editor where the first line is the title and later lines are the body.
  • --fill takes the title and body from Git commits; --fill-first uses the first commit, --fill-verbose includes commit messages and bodies. Explicit --title or --body values override the autofilled content.

Keep the body focused on the change, testing and known limitations. Do not assume a commit message is a suitable review description until you have read the resulting text.

6. Add reviewers, labels and issue linkage carefully

Repeat options when you need several values:

$ gh pr create \
    --base main \
    --head feature/fix-login \
    --title "Handle expired login sessions" \
    --body-file /path/to/review-body.txt \
    --reviewer REVIEWER_LOGIN \
    --reviewer TEAM_NAME \
    --label bug \
    --assignee @me

Use the exact GitHub login, team handle or label name the repository accepts. If the body says Fixes #123 or Closes #123, GitHub will close that issue when the pull request merges: only use that wording when closing the issue is genuinely intended.

Adding a project requires the project authorisation scope. If the command reports that scope is missing, the documented refresh command is:

$ gh auth refresh -s project

Warning

This changes local authentication state and may open a browser. Treat it as a deliberate security-sensitive step, and follow your organisation's approval rules.

7. Verify the created pull request

After creation, take the URL gh printed and query the pull request directly:

$ gh pr view 123 --json number,state,isDraft,baseRefName,headRefName,title,url
{"baseRefName":"main","headRefName":"feature/fix-login","isDraft":true,"number":123,"state":"OPEN","title":"Handle expired login sessions","url":"https://github.com/OWNER/REPOSITORY/pull/123"}

Compare the base and head with your intended branches, and check the title, draft state, reviewers and issue references in the web interface too. A successful command proves GitHub accepted the request; it does not prove the diff is safe to merge.

If you created the wrong pull request, do not try to undo it by rewriting branch history. Close it in GitHub, or use gh pr close 123 after checking the number. Closing does not delete commits or undo a branch push; removing a remote branch is a separate, potentially disruptive operation outside this workflow.

Common traps

  • Authentication required: check gh auth status; exit status 4 means authentication is required.
  • Wrong target: pass --base explicitly and inspect git diff BASE...HEAD before creating the request.
  • Unexpected push or fork prompt: stop, inspect the proposed destination, and use an explicit remote head that already exists when automatic publishing is not acceptable.
  • Cancelled prompt: the command uses exit status 2 for cancellation. Treat nothing as created until a URL is printed and gh pr view confirms it.
  • Failed run with recoverable input: the command provides --recover STRING. Use the recovery value only when it came from the failed gh pr create run; do not guess it.

Done means

  • Commits reviewed. The intended commits and base branch were checked before creation.
  • Fields explicit. Title, body, head and base were set explicitly, or the interactive choices were checked carefully.
  • Side effects deliberate. Any possible push, fork, project authorisation or issue-closing action was intended.
  • Result confirmed. The printed URL and gh pr view show the expected open or draft pull request.
  • Recovery understood. You know how to close a mistaken pull request without confusing closure with deleting its commits.