Use when merging pull requests, checking merge status, or configuring auto-merge. Trigger with merge, auto-merge, or readiness verification requests.
This skill provides comprehensive guidance for merging pull requests, checking merge status, verifying merge readiness, and configuring auto-merge using the GitHub API.
gh) installed and authenticated| Output Type | Format | Description |
|---|---|---|
| Merge status | JSON | Contains merged (boolean), state (OPEN/CLOSED/MERGED) |
| Readiness check | JSON | Contains ready (boolean), (MergeStateStatus), blocking reasons |
merge_state| Merge result | JSON | Contains success (boolean), merged_at (ISO timestamp), sha (commit hash) |
| Auto-merge status | JSON | Contains auto_merge_enabled (boolean), merge_method (MERGE/SQUASH/REBASE) |
| Exit codes | Integer | Standardized codes: 0=success, 1=invalid params, 2=not found, 3=API error, 4=auth, 5=already merged, 6=not mergeable |
eia_test_pr_merged.pyCopy this checklist and track your progress:
eia_test_pr_merged.pyeia_test_pr_merge_ready.pyeia_test_pr_merged.pyNEVER trust gh pr view --json state for merge state verification.
The REST API and gh pr view can return stale data. GraphQL queries against the GitHub API provide the authoritative, real-time merge state. Always use GraphQL for:
| Operation | Script | Purpose |
|---|---|---|
| Check if merged | eia_test_pr_merged.py | Verify PR merge status via GraphQL |
| Check readiness | eia_test_pr_merge_ready.py | Verify all merge requirements met |
| Execute merge | eia_merge_pr.py | Merge with specified strategy |
| Auto-merge | eia_set_auto_merge.py | Enable/disable auto-merge |
START: Need to merge a PR
│
├─► Is PR already merged?
│ Run: eia_test_pr_merged.py --pr <number> --repo <owner/repo>
│ │
│ ├─► Exit 1 (merged) → STOP: PR already merged
│ │
│ └─► Exit 0 (not merged) → Continue
│
├─► Is PR ready to merge?
│ Run: eia_test_pr_merge_ready.py --pr <number> --repo <owner/repo>
│ │
│ ├─► Exit 0 (ready) → Proceed to merge
│ │
│ ├─► Exit 1 (CI failing) → Fix CI or use --ignore-ci
│ │
│ ├─► Exit 2 (conflicts) → Resolve conflicts first
│ │
│ ├─► Exit 3 (threads) → Resolve threads or use --ignore-threads
│ │
│ └─► Exit 4 (reviews) → Get required approvals
│
├─► Should merge now or auto-merge?
│ │
│ ├─► Merge now:
│ │ Run: eia_merge_pr.py --pr <number> --repo <owner/repo> \
│ │ --strategy <merge|squash|rebase> [--delete-branch]
│ │
│ └─► Auto-merge when ready:
│ Run: eia_set_auto_merge.py --pr <number> --repo <owner/repo> \
│ --enable --merge-method <MERGE|SQUASH|REBASE>
│
└─► Verify merge completed:
Run: eia_test_pr_merged.py --pr <number> --repo <owner/repo>
Use BEFORE attempting any merge operation to avoid:
# Check if PR #123 in owner/repo is merged
python scripts/eia_test_pr_merged.py --pr 123 --repo owner/repo
Use to understand WHY a PR cannot be merged:
# Full readiness check
python scripts/eia_test_pr_merge_ready.py --pr 123 --repo owner/repo
# Skip CI check (emergency merge)
python scripts/eia_test_pr_merge_ready.py --pr 123 --repo owner/repo --ignore-ci
# Skip unresolved threads check
python scripts/eia_test_pr_merge_ready.py --pr 123 --repo owner/repo --ignore-threads
Use to execute the actual merge:
# Squash merge and delete branch
python scripts/eia_merge_pr.py --pr 123 --repo owner/repo --strategy squash --delete-branch
# Regular merge commit
python scripts/eia_merge_pr.py --pr 123 --repo owner/repo --strategy merge
# Rebase merge
python scripts/eia_merge_pr.py --pr 123 --repo owner/repo --strategy rebase
Use when PR needs to wait for CI or reviews:
# Enable auto-merge with squash
python scripts/eia_set_auto_merge.py --pr 123 --repo owner/repo --enable --merge-method SQUASH
# Disable auto-merge
python scripts/eia_set_auto_merge.py --pr 123 --repo owner/repo --disable
gh pr view --json state can be stale
# 1. Verify not already merged
python scripts/eia_test_pr_merged.py --pr 123 --repo owner/repo
# Exit 0 means not merged, continue
# 2. Check readiness
python scripts/eia_test_pr_merge_ready.py --pr 123 --repo owner/repo
# Exit 0 means ready
# 3. Merge with squash
python scripts/eia_merge_pr.py --pr 123 --repo owner/repo --strategy squash --delete-branch
# 4. Verify merge completed
python scripts/eia_test_pr_merged.py --pr 123 --repo owner/repo
# Exit 1 confirms merged
# 1. Enable auto-merge (will merge when CI passes and reviews approved)
python scripts/eia_set_auto_merge.py --pr 123 --repo owner/repo --enable --merge-method SQUASH
# 2. Later, check if merged
python scripts/eia_test_pr_merged.py --pr 123 --repo owner/repo
# 1. Check readiness ignoring CI
python scripts/eia_test_pr_merge_ready.py --pr 123 --repo owner/repo --ignore-ci
# 2. If ready (exit 0), merge
python scripts/eia_merge_pr.py --pr 123 --repo owner/repo --strategy merge
All scripts use standardized exit codes for consistent error handling:
| Code | Meaning | Description |
|---|---|---|
| 0 | Success | Operation completed successfully |
| 1 | Invalid parameters | Bad PR number, bad repo format |
| 2 | Resource not found | PR does not exist |
| 3 | API error | Network, rate limit, timeout |
| 4 | Not authenticated | gh CLI not logged in |
| 5 | Idempotency skip | PR already merged (no action needed) |
| 6 | Not mergeable | PR closed, conflicts, CI failing, reviews needed |
| Script | Exit 5 (Idempotency) | Exit 6 (Not Mergeable) |
|---|---|---|
| eia_test_pr_merged.py | PR already merged | N/A |
| eia_test_pr_merge_ready.py | N/A | Any blocking condition (see JSON for details) |
| eia_merge_pr.py | PR already merged | Conflicts, closed, not approved |
| eia_set_auto_merge.py | PR already merged | Cannot enable auto-merge |
# Check if PR is already merged
python scripts/eia_test_pr_merged.py --pr 123 --repo owner/repo
# Output: {"merged": false, "state": "OPEN"}
# Check if PR is ready to merge
python scripts/eia_test_pr_merge_ready.py --pr 123 --repo owner/repo
# Output: {"ready": true, "merge_state": "MERGEABLE"}
# Execute the merge
python scripts/eia_merge_pr.py --pr 123 --repo owner/repo --strategy squash --delete-branch
# Output: {"success": true, "merged_at": "2025-01-30T10:00:00Z"}
# Enable auto-merge - PR will merge when CI passes
python scripts/eia_set_auto_merge.py --pr 456 --repo owner/repo --enable --merge-method SQUASH
# Output: {"auto_merge_enabled": true}
eia_test_pr_merged.py to get authoritative stateeia_test_pr_merge_ready.py for blockerseia_test_pr_merge_ready.py to see blocking reasonsThis is temporary - GitHub is computing the merge state. Wait 5-10 seconds and retry. The scripts handle this with automatic retries.
Check:
The following PR merge operations are IRREVERSIBLE or have significant impact:
| Operation | Risk | Mitigation |
|---|---|---|
git push --force | Overwrites remote history, loses commits | NEVER use on shared branches; requires explicit approval |
| Merge without PR | Bypasses review process, no audit trail | ALWAYS use PR workflow |
| Squash merge | Original commits are lost from branch history | Acceptable if commits were WIP; verify first |
| Delete branch after merge | Cannot recover branch pointer | Commits still exist; can recreate branch if needed |
| Force merge ignoring CI | May introduce broken code to main | Only with explicit user approval and documented reason |
Verify you have a backup branch
# Create backup before any risky operation
git branch backup-pre-merge-$(date +%Y%m%d) HEAD
Confirm with orchestrator before:
--force push operations--ignore-ci)--ignore-threads)Log the operation details
echo "$(date): Merging PR #${PR_NUMBER} - Strategy: ${STRATEGY} - Flags: ${FLAGS}" >> merge-ops.log
eia_test_pr_merged.py after completionIf a merge introduces issues:
# Option 1: Revert the merge commit (creates new commit, preserves history)
git revert -m 1 <merge-commit-hash>
git push origin main
# Option 2: Reset to pre-merge state (DESTRUCTIVE - requires --force push)
# Only use if revert is not possible
git reset --hard <commit-before-merge>
git push --force origin main # REQUIRES EXPLICIT APPROVAL
# Option 3: Create hotfix branch and new PR
git checkout -b hotfix/revert-pr-${PR_NUMBER}
git revert -m 1 <merge-commit-hash>
git push -u origin hotfix/revert-pr-${PR_NUMBER}
gh pr create --title "Revert PR #${PR_NUMBER}" --body "Reverting due to: [REASON]"
All scripts are in the scripts/ directory of this skill:
scripts/
├── eia_test_pr_merged.py # Check if PR is merged
├── eia_test_pr_merge_ready.py # Check merge eligibility
├── eia_merge_pr.py # Execute merge
└── eia_set_auto_merge.py # Enable/disable auto-merge
Each script outputs JSON to stdout for easy parsing by automation tools.