Difficulty: Beginner
What makes a good pull request? Describe your ideal PR workflow and review process.
A good pull request is small, focused, well-described, and easy to review. The ideal PR changes fewer than 400 lines, addresses a single concern, and includes a clear description of what changed and why.
PR anatomy: - Title: Concise summary following commit conventions (feat:, fix:, etc.) - Description: What changed, why, how to test, screenshots for UI changes - Size: Small and focused. Large PRs get rubber-stamped, small PRs get thorough reviews. - Tests: Include or update tests that cover the changes - Self-review: Review your own diff before requesting others
Branch protection rules enforce quality: - Require PR reviews before merging (minimum 1-2 approvals) - Require status checks to pass (CI/CD pipeline) - Require up-to-date branches before merging - Restrict who can push to protected branches
CODEOWNERS file automatically assigns reviewers based on file paths, ensuring domain experts review relevant changes. PR templates standardize descriptions so reviewers always get the context they need.
# .github/PULL_REQUEST_TEMPLATE.md
## What
<!-- Brief description of changes -->
## Why
<!-- Motivation / link to issue -->
Closes #___
## How
<!-- Implementation approach -->
## Testing
- [ ] Unit tests added/updated
- [ ] Manual testing completed
- [ ] No regressions found
## Screenshots
<!-- For UI changes, add before/after screenshots -->
---
# .github/CODEOWNERS
# Automatically request reviews from domain experts
*.ts @backend-team
*.tsx @frontend-team
src/auth/ @security-team
src/payments/ @payments-team
.github/workflows/ @devops-team
prisma/ @backend-team @dba-team
Dockerfile @devops-team
PR templates ensure consistent descriptions. CODEOWNERS auto-assigns reviewers by file path. This scales code review as the team grows.
# GitHub branch protection rules (via gh CLI)
gh api repos/{owner}/{repo}/branches/main/protection -X PUT \
--input - <<EOF
{
"required_status_checks": {
"strict": true,
"contexts": ["ci/test", "ci/lint", "ci/build"]
},
"required_pull_request_reviews": {
"required_approving_review_count": 2,
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true
},
"enforce_admins": true,
"restrictions": null
}
EOF
# What these rules enforce:
# 1. CI checks must pass before merge
# 2. Branch must be up-to-date with main
# 3. 2 approving reviews required
# 4. Stale reviews dismissed on new pushes
# 5. CODEOWNERS must approve their files
# 6. Even admins follow the rules
Branch protection prevents direct pushes to main and ensures quality gates. dismiss_stale_reviews means new pushes reset previous approvals, requiring fresh review.
# Create a PR from command line
gh pr create --title "feat: add user authentication" \
--body "## What\nAdded login and registration endpoints" \
--reviewer "teammate1,teammate2" \
--assignee "@me" \
--label "feature"
# List open PRs
gh pr list
# Review a PR
gh pr diff 42
gh pr review 42 --approve
gh pr review 42 --request-changes --body "Please add tests"
# Merge strategies:
# 1. Merge commit: preserves all commits + merge commit
gh pr merge 42 --merge
# 2. Squash merge: all commits become one (clean history)
gh pr merge 42 --squash
# 3. Rebase merge: replays commits on main (linear, no merge commit)
gh pr merge 42 --rebase
# Check PR status
gh pr checks 42
gh pr status
# Auto-merge when checks pass
gh pr merge 42 --auto --squash
gh CLI streamlines PR workflows. Squash merge is recommended for feature PRs to keep main history clean. Auto-merge saves time waiting for CI.
Pull Requests, Code Review, PR Templates, Branch Protection, CODEOWNERS