Clean and normalize a large backlog of GitHub pull requests in messy repositories...
Clean and normalize large backlogs of GitHub pull requests systematically while keeping the default branch stable and deployable. This skill provides a comprehensive workflow for triaging, reviewing, rebasing, testing, and dispositioning PRs at scale, ensuring every PR ends in one of three states: merged safely, closed with reason, or explicitly deferred.
NEW: Integrates pr-comment-analysis subskill to systematically extract, analyze, and prioritize existing PR review feedback. This helps avoid re-litigating issues reviewers already identified, catch hidden impacts through automated analysis, and make informed merge/close/defer decisions based on the complete feedback picture.
Use this skill when:
CRITICAL RULES - Never violate these:
Discover the environment before taking any action.
# List all branches
git branch -a
# Identify protected/default branch
gh repo view --json defaultBranchRef
Look for: main, master, or other protected branches
Check for these files to determine tech stack:
package.json, .nvmrcrequirements.txt, pyproject.toml, setup.py, Pipfilepom.xml, build.gradle, build.gradle.ktsgo.mod, go.sumCargo.toml, Cargo.lockGemfile, Gemfile.lockCheck for CI/build configs:
.github/workflows/*Jenkinsfile.gitlab-ci.ymlazure-pipelines.yml.circleci/config.ymlExtract test commands from:
.github/workflows/*.yml for test stepspackage.json: scripts.testpyproject.toml: [tool.pytest] or [tool.tox]pom.xml: <build><plugins> for surefire/failsafeCargo.toml: cargo test is standardCommon test commands by ecosystem:
# Node.js
npm test
npm run test:unit
npm run test:integration
# Python
pytest
python -m pytest
tox
python -m unittest discover
# Java
mvn test
./gradlew test
# Go
go test ./...
# Rust
cargo test
# Checkout default branch
git checkout <default_branch>
git pull origin <default_branch>
# Run identified test command
<test_command>
Record:
If tests fail on default branch:
Create a comprehensive inventory of all open PRs.
# List all open PRs with detailed info
gh pr list --state open --json number,title,author,createdAt,updatedAt,additions,deletions,files,labels,statusCheckRollup --limit 1000 > pr_inventory.json
For each PR, document:
See scripts/analyze_pr_backlog.py for automated inventory generation.
Based on title, description, and diff, classify as:
bugfix: Fixes reported bugs or errorsfeature: Adds new functionalityrefactor: Restructures code without changing behaviorinfra: CI, build, tooling, deployment, configsdocs: Documentation-only changesmixed: Contains multiple categories (upgrade risk)Low Risk:
Medium Risk:
High Risk:
Store in pr_backlog_analysis.md:
# PR Backlog Analysis
**Repository**: owner/repo
**Analysis Date**: 2025-01-19
**Total Open PRs**: 47
**Default Branch**: main
**Test Status**: β
Passing (baseline)
## PR Inventory
| PR# | Title | Author | Age (days) | Type | Risk | CI | Files | +/- |
|-----|-------|--------|------------|------|------|-----|-------|-----|
| 123 | Fix auth timeout | user1 | 45 | bugfix | medium | β
| 3 | +25/-10 |
| 124 | Update README | user2 | 120 | docs | low | β
| 1 | +15/-5 |
| 125 | Refactor database layer | user3 | 200 | refactor | high | β | 25 | +500/-300 |
## Stale Candidates (>90 days, no recent activity)
- PR #124 (120 days)
- PR #125 (200 days)
Establish consistent rules for all PR processing.
Stale threshold: 90 days with no commits or comments
For stale PRs:
stale-candidateStale closure template:
This PR has been inactive for >90 days and the branch is significantly behind the current `main` branch.
To revive this work:
1. Rebase on current main: `git rebase origin/main`
2. Resolve any conflicts
3. Ensure tests pass
4. Open a new PR with updated context
Closing for now to keep the backlog manageable. Thank you for the contribution!
Default: Squash and merge
Use merge commits only if:
Rebase before merge:
If automated tests exist:
If tests are broken on default branch:
If no tests exist:
Process PRs in this priority order:
Priority 1: Low-hanging fruit
Priority 2: Value-add features 3. Small to medium feature PRs (recent, low-to-medium risk)
Priority 3: Complex work 4. Refactors and high-risk PRs
Priority 4: Problem cases 5. Very old or heavily conflicted PRs
Within each category, prioritize:
Execute this workflow for each PR in triage order.
# View PR details
gh pr view <PR_NUMBER>
# Check linked issues
gh issue view <ISSUE_NUMBER>
Determine if still relevant:
If clearly obsolete:
obsoleteTemplate for obsolete closure:
This PR is no longer relevant because [specific reason]:
- [Problem was solved by PR #XYZ]
- [Feature is no longer needed per issue #ABC discussion]
- [Architecture has moved in a different direction]
Closing this PR. Thank you for the contribution!
Check CI status:
gh pr checks <PR_NUMBER>
If CI is green (β ):
If CI is red (β):
View CI logs:
gh run view <RUN_ID> --log-failed
# Fetch PR branch
gh pr checkout <PR_NUMBER>
# OR manually:
git fetch origin pull/<PR_NUMBER>/head:pr-<PR_NUMBER>
git checkout pr-<PR_NUMBER>
# Rebase onto latest default branch
git fetch origin
git rebase origin/<default_branch>
Resolve conflicts:
Conflict resolution rules:
After resolving conflicts:
# Ensure code compiles (if applicable)
npm run build # or mvn compile, cargo build, etc.
# Run tests for affected modules
<test_command>
Test scope:
Push rebased branch:
# Use force-with-lease to avoid clobbering external changes
git push origin pr-<PR_NUMBER> --force-with-lease
Identify blast radius:
List affected modules/packages
# View changed files
gh pr diff <PR_NUMBER> --name-only
Detect impact areas:
Detect change type:
If PR mixes unrelated changes:
mixedExtract and Analyze PR Comments (NEW - Subskill Integration):
Use the pr-comment-analysis subskill to systematically analyze existing PR feedback:
Extract all PR comments:
# Navigate to repository
cd /path/to/repo
# Run pr-comment-analysis comment grabber
python /path/to/skills/pr-comment-analysis/scripts/pr-comment-grabber.py owner/repo <PR_NUMBER>
This creates pr-code-review-comments/pr<PR_NUMBER>-code-review-comments.json
Analyze extracted comments:
Integrate comment insights into PR disposition:
For PRs with substantive review feedback:
Comment analysis outcomes:
Document comment resolution:
## PR #123 Comment Analysis
**Total comments**: 15
**Critical issues**: 2 (both addressed)
**Design improvements**: 5 (3 addressed, 2 deferred to #456)
**Style nitpicks**: 8 (addressed)
**Key insights:**
- SQL injection vulnerability fixed (validated with parameterized queries)
- Cache invalidation refactored (impact: 4 other files updated)
- Breaking API change deferred (affects 12 consumers outside PR scope)
Why use pr-comment-analysis during backlog cleanup:
For bugfix PRs:
β Must have:
β If no test exists and repo has tests:
For feature PRs:
β Must have:
expect(true).toBe(true))For refactor PRs:
β Validation:
Execute tests:
# Run affected module tests
<test_command_for_module>
# Or run full suite
<test_command>
Do not assume correctness without test execution when tests exist.
Merge criteria (all must be satisfied):
If all criteria satisfied:
# Squash and merge (preferred)
gh pr merge <PR_NUMBER> --squash --delete-branch
# Use this commit message format:
# <Title> (#<PR_NUMBER>)
#
# <Brief summary of change>
# <Why this change was needed>
If salvageable but needs fixes:
Apply minimal changes to make mergeable:
# Make necessary fixes
git commit -m "Fix: <specific issue>"
git push origin pr-<PR_NUMBER> --force-with-lease
# Re-run tests
<test_command>
# Merge once criteria satisfied
gh pr merge <PR_NUMBER> --squash --delete-branch
If too noisy or requires excessive rework:
Create clean replacement PR:
# Create new branch from default
git checkout <default_branch>
git pull origin <default_branch>
git checkout -b clean-<feature_name>
# Cherry-pick or reimplement only essential changes
# (see Phase 6B for cherry-picking strategy)
# Open new PR
gh pr create --title "<Clear title>" --body "Cleaned up version of #<OLD_PR_NUMBER>"
If obsolete, unsafe, or too costly:
Close with clear reason:
gh pr close <PR_NUMBER> --comment "Closing because [specific reason]:
- [Obsolete: Superseded by #XYZ]
- [Unsafe: Introduces breaking changes without migration path]
- [Too costly: Requires major refactor beyond PR scope]
Thank you for the contribution!"
When multiple large/conflicting PRs affect the same areas:
# Create integration branch
git checkout <default_branch>
git pull origin <default_branch>
git checkout -b integration/<feature_area>
# Sequentially merge PRs into integration branch
gh pr checkout <PR_1>
git checkout integration/<feature_area>
git merge pr-<PR_1> --no-ff
# Resolve conflicts, run tests
<test_command>
# Repeat for each related PR
gh pr checkout <PR_2>
git checkout integration/<feature_area>
git merge pr-<PR_2> --no-ff
<test_command>
# Analyze combined impact
<test_command>
# Cherry-pick stable parts back to clean PRs
# (see Strategy B)
Benefits:
When a PR contains both useful and problematic changes:
# Identify valuable commits
git log --oneline pr-<PR_NUMBER>
# Create clean branch from default
git checkout <default_branch>
git checkout -b cherry-picked-<feature>
# Cherry-pick specific commits
git cherry-pick <commit_sha_1>
git cherry-pick <commit_sha_2>
# Test cherry-picked changes
<test_command>
# Open new focused PR
gh pr create --title "Clean version: <feature>" --body "Cherry-picked valuable changes from #<OLD_PR>"
Use when:
If tests exist but coverage is weak:
Identify critical flows:
Before risky merges:
If no tests exist at all:
Only merge:
Avoid merging:
Consider adding tests first:
# Create baseline characterization tests
# Document current behavior, even if not ideal
# Provides safety net for future changes
For each stale-candidate PR:
Verify stale criteria:
Check for dependencies:
Close if truly stale:
gh pr close <PR_NUMBER> --comment "<stale closure template from Phase 3.1>"
# Add label
gh pr edit <PR_NUMBER> --add-label "stale-closed"
Label consistently:
stale-closed: Closed due to inactivityobsolete: Closed because no longer relevantsuperseded: Closed because replaced by newer PRMaintain progress tracking in pr_cleanup_report.md:
# PR Cleanup Report
**Repository**: owner/repo
**Cleanup Started**: 2025-01-19
**Cleanup Completed**: 2025-01-22
**Default Branch**: main
## Summary
**Starting State:**
- Total open PRs: 47
- Stale PRs (>90 days): 18
- Failing CI: 12
- Passing CI: 35
**Final State:**
- Merged: 28
- Closed (obsolete): 11
- Closed (stale): 6
- Deferred (needs discussion): 2
## Merged PRs
| PR# | Title | Type | Risk | Outcome |
|-----|-------|------|------|---------|
| 123 | Fix auth timeout | bugfix | medium | β
Merged after rebase |
| 126 | Add logging | infra | low | β
Merged (squash) |
## Closed PRs
| PR# | Title | Reason | Age (days) |
|-----|-------|--------|------------|
| 124 | Update README | Superseded by #130 | 120 |
| 125 | Refactor DB | Too risky without tests | 200 |
## Deferred PRs
| PR# | Title | Reason | Next Steps |
|-----|-------|--------|------------|
| 140 | Major API redesign | Needs architecture discussion | Schedule RFC review |
## Default Branch Status
**Before cleanup:**
- CI status: β
Passing
- Test count: 450 tests
- Coverage: ~65%
**After cleanup:**
- CI status: β
Passing
- Test count: 465 tests (+15 from merged PRs)
- Coverage: ~67% (+2%)
- No regressions introduced
Termination condition:
Stop when:
analyze_pr_backlog.py
python scripts/analyze_pr_backlog.py owner/reporebase_and_test.sh
./scripts/rebase_and_test.sh <PR_NUMBER>close_stale_prs.py
python scripts/close_stale_prs.py owner/repo --threshold 90github_api_reference.md
gh) commands for PR managementconflict_resolution_patterns.md
test_frameworks_reference.md
pr-comment-analysis (skills/pr-comment-analysis/)
skills/pr-comment-analysis/SKILL.md for complete documentationStep 1: Initial setup
# Clone the repo and ensure clean state
git clone https://github.com/owner/repo
cd repo
git checkout <default_branch>
# Verify tests run
<identify and run test command>
Step 2: Generate inventory
# Use the analysis script
python scripts/analyze_pr_backlog.py owner/repo
# Review the generated pr_backlog_analysis.md
Step 3: Start processing
# Process PRs in priority order (Phase 4)
# For each PR, follow Phase 5 standard flow
# Use automation scripts to speed up:
./scripts/rebase_and_test.sh <PR_NUMBER>
Step 4: Handle special cases
# For complex PRs, use Phase 6 strategies
# For stale PRs, use Phase 8 process
Step 5: Document and complete
# Fill out pr_cleanup_report.md as you progress
# Ensure all PRs are dispositioned
# Verify default branch stability
1. Document decisions
2. Communicate changes
3. Maintain stability
4. Prefer automation
5. Track progress
6. Know when to defer
β Merging without testing
β Force pushing to default branch
β Modifying unrelated files
β Assuming CI failures are flaky
β Closing PRs without explanation
β Inventing repository conventions
Problem: Rebase conflicts are overwhelming
Problem: Tests fail after rebase but not on PR branch
Problem: CI is red on default branch (baseline broken)
Problem: PR author hasn't responded in months
Problem: Unsure if PR is still relevant