GitHub CLI Cheatsheet

Reviews and Merging

Use this GitHub CLI reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Submitting a Review

gh pr review submits a whole review, not a line comment. One of the three verdict flags is required non-interactively.

gh pr review 123 --approve
gh pr review 123 --approve --body "ship it"
gh pr review 123 --request-changes -b "needs a test for the empty case"
gh pr review 123 --comment -b "one nit, otherwise fine"
gh pr review 123 --request-changes --body-file review.md
gh pr review 123 --comment --body-file - < notes.txt
gh pr review                              # interactive, current branch
FlagVerdict
-a, --approveApprove
-r, --request-changesRequest changes, body is required
-c, --commentComment only, no verdict, body is required
-b, --bodyReview body text
-F, --body-fileRead the body from a file, - for stdin

With no flags it opens a prompt, then your editor for the body. Per-line review comments are not exposed here, use --web on gh pr view or the gh api pulls review-comments endpoint.

Watching Checks

gh pr checks                              # current branch's PR
gh pr checks 123
gh pr checks 123 --watch                  # refresh until every check finishes
gh pr checks 123 --watch --interval 5
gh pr checks 123 --watch --fail-fast      # bail on the first failure
gh pr checks 123 --required                # only required checks
gh pr checks 123 --json name,state,link
gh pr checks 123 --json state --jq '[.[] | select(.state=="FAILURE")] | length'
gh pr checks 123 --web

--watch blocks and redraws until the run set completes, then exits non-zero if anything failed. That makes it usable as a gate:

gh pr checks --watch --fail-fast && gh pr merge --squash --delete-branch

Exit codes matter here: 0 every check passed, 8 checks are still pending, 1 a check failed, 2 cancelled, 4 not authenticated. Do not treat every non-zero code as "a check failed".

Merging

gh pr merge 123 --squash
gh pr merge 123 --merge
gh pr merge 123 --rebase
gh pr merge 123 --squash --delete-branch
gh pr merge 123 --squash -t "feat: add login" -b "closes #42"
gh pr merge 123 --merge --body-file merge-notes.md
gh pr merge 123 --auto --squash           # merge once requirements pass
gh pr merge 123 --disable-auto
gh pr merge 123 --admin --squash          # bypass branch protection
gh pr merge 123 --squash --match-head-commit 9a3f21c
gh pr merge                               # interactive, current branch
FlagEffect
-s, --squashOne squashed commit onto the base
-m, --mergeA merge commit
-r, --rebaseReplay the commits onto the base
--autoEnable auto-merge, GitHub merges when checks and reviews pass
--disable-autoTurn auto-merge back off
-d, --delete-branchDelete the remote branch, and the local one if checked out
--adminMerge with admin privileges even if requirements are unmet
-t, --subject, -b, --bodyCommit subject and body
-F, --body-fileCommit body from a file
-A, --author-emailAuthor email for the merge commit
--match-head-commit <SHA>Refuse the merge unless the head is still that SHA

--match-head-commit is the safety belt for automation. Between reading a PR and merging it someone can push another commit, and this flag turns that race into a clean failure instead of merging code you never reviewed.

A merge method the repo has disabled is rejected, so check gh repo view --json squashMergeAllowed,mergeCommitAllowed,rebaseMergeAllowed if a flag errors out.

Auto-Merge

--auto queues the merge instead of performing it. GitHub waits until required checks pass and required reviews land.

gh pr merge 123 --auto --squash --delete-branch
gh pr merge 123 --disable-auto
gh pr view 123 --json autoMergeRequest

Auto-merge must be enabled on the repository first (gh repo edit --enable-auto-merge), and the branch needs at least one required status check, otherwise the API rejects the request.

Review Workflow

A realistic pass over someone else's PR, all read-only until the last line.

gh pr status                              # what is waiting on me
gh pr list --search "review-requested:@me"
gh pr view 123 --comments                 # read the discussion
gh pr diff 123 --exclude "*.lock"         # read the change
gh pr checkout 123                        # run it locally
gh pr checks 123                          # CI state
gh pr review 123 --approve -b "lgtm"

And the author's side once approved:

gh pr checks --watch --fail-fast
gh pr merge --squash --delete-branch
git checkout main && git pull

Inspecting Review State

Reviews and approvals are fields on the PR, so --json answers "who approved" without opening a browser.

gh pr view 123 --json reviews \
  --jq '.reviews[] | "\(.author.login) \(.state)"'
gh pr view 123 --json reviewDecision --jq .reviewDecision
gh pr view 123 --json mergeable,mergeStateStatus
gh pr list --json number,title,reviewDecision \
  --jq '.[] | select(.reviewDecision=="APPROVED") | .number'
gh pr view 123 --json latestReviews \
  --template '{{range .latestReviews}}{{.author.login}} {{.state}}{{"\n"}}{{end}}'

reviewDecision is the rolled-up verdict (APPROVED, CHANGES_REQUESTED, REVIEW_REQUIRED), and latestReviews collapses each reviewer to their most recent verdict. reviews is the full history, which double counts anyone who reviewed twice.