| name | gh-pr-merge |
| description | Merge GitHub pull requests using gh CLI. Supports merge, squash, and rebase strategies with auto-merge option. Use when PR is approved and ready to merge. |
| allowed-tools | Bash, Read, Grep |
| handoffs | [object Object] |
GitHub PR Merge Skill
Merge approved pull requests using the gh CLI with intelligent merge strategies.
When to Use
- User says "merge the PR" or "merge this pull request"
- PR is approved and ready to merge
- User wants to enable auto-merge
- After all CI checks pass and reviews are approved
- User wants to merge with specific strategy (squash/rebase)
Prerequisites
Verify GitHub CLI is installed and authenticated:
gh --version
gh auth status
Verify merge permissions:
gh repo view --json viewerPermission --jq '.viewerPermission'
# Should be: WRITE, MAINTAIN, or ADMIN
Execution Workflow
Step 1: Pre-Merge Validation
Before merging, verify the PR is ready:
# Get PR status
gh pr view 123 --json \
state,isDraft,mergeable,reviewDecision,\
statusCheckRollup,commits
# Check if:
# - state == "OPEN"
# - isDraft == false
# - mergeable == "MERGEABLE"
# - reviewDecision == "APPROVED" (if required)
# - statusCheckRollup shows all required checks passed
Validation Checklist:
- PR is open (not closed/merged)
- PR is not a draft
- No merge conflicts
- Required reviews approved
- All required CI checks passed
- No blocking conversations
Step 2: Choose Merge Strategy
Determine merge strategy based on:
- Repository settings
- Team conventions
- PR characteristics
Merge Strategies:
Merge Commit (
--merge):- Preserves all commits and history
- Creates merge commit
- Use for: Feature branches with meaningful commit history
Squash and Merge (
--squash):- Combines all commits into one
- Clean linear history
- Use for: Feature PRs with many WIP commits
Rebase and Merge (
--rebase):- Replays commits on base branch
- No merge commit
- Use for: Clean commit history, linear timeline
Auto-detect strategy:
# Check repository default merge method
MERGE_METHOD=$(gh api repos/:owner/:repo --jq '
if .allow_squash_merge and .allow_merge_commit and .allow_rebase_merge then
"ask"
elif .allow_squash_merge then
"squash"
elif .allow_rebase_merge then
"rebase"
elif .allow_merge_commit then
"merge"
else
"error"
end
')
Step 3: Merge the PR
Standard merge:
gh pr merge 123 --squash
With custom commit message:
gh pr merge 123 --squash \
--subject "Add user authentication" \
--body "$(cat <<'EOF'
Implements JWT-based authentication with:
- Login/logout endpoints
- Token refresh mechanism
- Password hashing with bcrypt
- Session management
Closes #45
EOF
)"
Auto-merge (merge when checks pass):
gh pr merge 123 --auto --squash
Delete branch after merge:
gh pr merge 123 --squash --delete-branch
Admin merge (bypass protections):
gh pr merge 123 --squash --admin
# ⚠️ Use with extreme caution!
Step 4: Verify Merge
After merging, confirm success:
# Check PR status
gh pr view 123 --json state,merged,mergedAt
# Verify base branch updated
git fetch origin
git log origin/main -1 --oneline
# Check if branch deleted
gh api repos/:owner/:repo/branches/feature-name 2>&1 | grep -q "Not Found"
Step 5: Report Success
Present merge result:
✓ PR #123 merged successfully
Strategy: Squash and merge
Merged by: @username
Merged at: 2024-01-01 15:30:00
Branch deleted: Yes
Commit: abc1234 - "Add user authentication"
Base branch: main updated
🔗 [View merged PR](https://github.com/owner/repo/pull/123)
Common Scenarios
Scenario 1: Simple Squash Merge
# Verify PR is ready
gh pr view 123 --json reviewDecision,mergeable
# reviewDecision: "APPROVED", mergeable: "MERGEABLE"
# Check CI
gh pr checks 123
# All checks passed ✓
# Merge with squash
gh pr merge 123 --squash --delete-branch
echo "✓ PR #123 merged and branch deleted"
Scenario 2: Auto-Merge When Checks Pass
# Enable auto-merge for approved PR waiting on CI
gh pr merge 123 --auto --squash
echo "⏳ Auto-merge enabled. PR will merge when all checks pass."
# Watch check progress
gh pr checks 123 --watch
Scenario 3: Merge with Custom Message
# Merge with detailed commit message
gh pr merge 123 --squash \
--subject "feat: add user authentication system" \
--body "$(cat <<'EOF'
Implements comprehensive authentication:
Features:
- JWT token-based auth
- Secure password hashing
- Session management
- OAuth2 integration
Breaking Changes:
- Auth header format changed from Bearer to JWT
Migration Guide:
Update client auth headers to use new JWT format.
Closes #45, #67
Related: #23
Co-authored-by: Alice <alice@example.com>
Co-authored-by: Bob <bob@example.com>
EOF
)"
Scenario 4: Merge with Rebase for Clean History
# For PRs with clean, meaningful commits
gh pr view 123 --json commits
# Verify each commit is good
gh pr view 123 --json commits \
| jq -r '.commits[] | .messageHeadline'
# Merge with rebase to preserve commits
gh pr merge 123 --rebase --delete-branch
Scenario 5: Conditional Merge Based on Checks
# Only merge if all conditions met
PR_NUM=123
# Get PR data
PR_DATA=$(gh pr view $PR_NUM --json \
reviewDecision,mergeable,statusCheckRollup,isDraft)
REVIEW=$(echo "$PR_DATA" | jq -r '.reviewDecision')
MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable')
IS_DRAFT=$(echo "$PR_DATA" | jq -r '.isDraft')
CHECKS=$(echo "$PR_DATA" | jq -r '.statusCheckRollup[] | select(.isRequired == true) | .conclusion')
# Validate
if [[ "$REVIEW" == "APPROVED" ]] && \
[[ "$MERGEABLE" == "MERGEABLE" ]] && \
[[ "$IS_DRAFT" == "false" ]] && \
! echo "$CHECKS" | grep -qv "SUCCESS"; then
gh pr merge $PR_NUM --squash --delete-branch
echo "✓ PR merged successfully"
else
echo "⚠ PR not ready to merge:"
echo " Review: $REVIEW"
echo " Mergeable: $MERGEABLE"
echo " Draft: $IS_DRAFT"
echo " Checks: $CHECKS"
exit 1
fi
Scenario 6: Batch Merge Approved PRs
# Merge all approved PRs from a milestone
gh pr list --json number,reviewDecision,mergeable,milestone \
| jq -r '.[] |
select(.reviewDecision == "APPROVED") |
select(.mergeable == "MERGEABLE") |
select(.milestone.title == "v1.0") |
.number' \
| while read pr; do
echo "Merging PR #$pr..."
gh pr merge $pr --squash --delete-branch
sleep 2 # Rate limiting
done
Advanced Options
Merge Queue
For repositories with merge queues enabled:
# Add to merge queue
gh pr merge 123 --auto --squash
# Check queue position
gh api repos/:owner/:repo/pulls/123/merge_queue \
| jq '.position'
Protected Branch Bypass
For admin users only:
# Bypass branch protections (use with extreme caution)
gh pr merge 123 --admin --squash
# This bypasses:
# - Required reviews
# - Status checks
# - Restrictions
Merge with Required Linear History
# For repos requiring linear history
gh pr merge 123 --rebase
# Or squash to maintain linearity
gh pr merge 123 --squash
Merge Dependabot PRs
# Auto-merge approved Dependabot PRs
gh pr list --author app/dependabot \
--json number,reviewDecision \
| jq -r '.[] | select(.reviewDecision == "APPROVED") | .number' \
| while read pr; do
gh pr merge $pr --auto --squash --delete-branch
done
Error Handling
Error: "Pull request is not mergeable"
- Cause: Merge conflicts exist
- Solution: Resolve conflicts first
git fetch origin
git checkout feature-branch
git merge origin/main
# Resolve conflicts
git push
Error: "Required status checks have not succeeded"
- Cause: CI checks failing or pending
- Solution: Wait for checks or fix failures
gh pr checks 123 --watch
Error: "Review required"
- Cause: PR needs approval
- Solution: Request reviews
gh pr review 123 --approve
# Or request from others:
gh pr edit 123 --add-reviewer user1,user2
Error: "Branch protection rule violations"
- Cause: Branch protections not met
- Solution: Satisfy requirements or use admin override (if authorized)
Error: "Pull request is closed"
- Cause: PR already merged or closed
- Solution: Verify PR status
gh pr view 123 --json state,merged
Error: "Auto-merge not allowed"
- Cause: Repository doesn't have auto-merge enabled
- Solution: Use standard merge or enable in repository settings
Best Practices
- Always validate first: Check reviews, checks, and mergeable status
- Choose appropriate strategy:
- Squash for feature branches with messy history
- Rebase for clean commits
- Merge for preserving exact history
- Delete branches: Use
--delete-branchto clean up - Write good merge messages: Provide context for squash merges
- Use auto-merge for trusted PRs: Let CI complete before merging
- Never force merge: Avoid
--adminunless absolutely necessary - Verify after merge: Check base branch was updated
- Follow team conventions: Use team's preferred merge strategy
- Wait for required checks: Don't bypass failing checks
- Review before merge: One final check of the code
Merge Strategy Decision Tree
Is commit history clean and meaningful?
├─ Yes → Use --rebase
└─ No
├─ Multiple WIP commits? → Use --squash
└─ Want to preserve exact history? → Use --merge
Does repository require linear history?
├─ Yes → Use --squash or --rebase
└─ No → Any strategy works
Is this a hotfix or emergency?
├─ Yes → Use --merge (preserve all context)
└─ No → Follow normal team conventions
Related Skills
gh-pr-view- View PR details before merginggh-pr-create- Create pull requestsgh-pr-review- Review and approve PRsgh-pr-ready- Mark draft as ready
Limitations
- Requires write access to repository
- Cannot merge if branch protections not satisfied (without admin override)
- Auto-merge requires repository setting enabled
- Squash merge may lose commit-level context
- Rebase may cause issues with force-pushed branches
See Also
- GitHub CLI docs: https://cli.github.com/manual/gh_pr_merge
- Merge strategies: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges
- Branch protections: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches