--- id: wiki-2026-0508-pull-request-pr title: Pull Request (PR) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [PR, Merge Request, Code Review PR] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [git, github, code-review, workflow] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: shell framework: git --- # Pull Request (PR) ## 매 한 줄 > **"매 PR — small, single-purpose, reviewable diff"**. 매 GitHub flow 의 unit of change. 2026 modern: AI-assisted review (Copilot, CodeRabbit, Claude) 가 매 first-pass triage, 매 human reviewer 의 architecture / intent 에 집중. ## 매 핵심 ### 매 Why small PRs - 매 review latency: 200 LOC PR 의 review time ≈ linear, >400 LOC 의 superlinear (review fatigue). - 매 bug detection: small PR 의 defect rate 의 lower (Microsoft 2013 study, 2024 GitHub data confirm). - 매 revert cost: small PR 의 cleanly revertable. - 매 mental model: reviewer 의 hold entire diff in head. ### 매 PR anatomy - **Title**: conventional commit prefix (`feat:`, `fix:`, `refactor:`, `docs:`, `chore:`). - **Description**: WHY (not WHAT — diff shows WHAT). Link issue (`Closes #123`). - **Test plan**: explicit checklist of manual / automated verification. - **Screenshots / videos**: UI changes 의 mandatory. - **Breaking changes**: top-level callout. ### 매 GitHub flow (vs Git flow) 1. `main` always-deployable. 2. Branch from `main` (`feat/xyz`). 3. Commit + push. 4. Open PR early (draft PR for WIP). 5. CI + review. 6. Squash-merge → deploy. ### 매 응용 1. Open-source contribution (fork → PR). 2. Internal team workflow (trunk-based). 3. AI agent autonomous PRs (Devin, Claude Code, Cursor agents 의 emit PR). ## 💻 패턴 ### Small focused PR ```bash # 매 single concern per PR git checkout -b feat/add-user-avatar main # ... edits limited to avatar feature ... git add src/components/Avatar.tsx src/components/Avatar.test.tsx git commit -m "feat(user): add Avatar component with fallback initials" git push -u origin feat/add-user-avatar gh pr create --fill --base main ``` ### Conventional commit message ```text feat(auth): add OAuth2 PKCE flow for SPA clients - Replace implicit grant (deprecated) with PKCE - Add code_verifier generation in auth-store - Update redirect handler to exchange code Closes #482 BREAKING CHANGE: SPA clients must upgrade to PKCE flow. ``` ### PR description template (.github/pull_request_template.md) ```markdown ## Why ## What changed - bullet 1 - bullet 2 ## Test plan - [ ] unit tests pass (`pnpm test`) - [ ] manual: login → logout flow - [ ] verified on Safari + Firefox ## Screenshots | Before | After | |---|---| | ... | ... | ``` ### Stacked PRs (Graphite / spr workflow) ```bash # 매 large feature 을 매 dependent small PRs 로 split gt create -m "feat: add User model" # PR #1 base=main gt create -m "feat: add User API" # PR #2 base=PR#1 gt create -m "feat: add User UI" # PR #3 base=PR#2 gt submit --stack ``` ### Squash-merge with clean message ```bash gh pr merge 482 --squash --delete-branch \ --subject "feat(auth): add OAuth2 PKCE flow (#482)" \ --body "$(gh pr view 482 --json body -q .body)" ``` ### CI gate (GitHub Actions) ```yaml # .github/workflows/pr.yml on: pull_request jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 - run: pnpm install --frozen-lockfile - run: pnpm lint && pnpm typecheck && pnpm test - run: pnpm build ``` ### AI review automation (CodeRabbit / Claude PR review) ```yaml # .github/workflows/claude-review.yml on: pull_request jobs: review: runs-on: ubuntu-latest steps: - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} mode: review model: claude-opus-4-7 ``` ### Review etiquette (comment style) ```text # 매 nit (preference, non-blocking) nit: prefer `const` over `let` here # 매 question (clarification) q: why bypass the cache here? # 매 blocker (must fix before merge) blocker: this regex is catastrophic backtracking, see #391 # 매 praise praise: nice extraction of the retry helper ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | <200 LOC, single concern | merge as-is | | >400 LOC | split into stacked PRs | | WIP, want early feedback | draft PR | | breaking change | explicit BREAKING CHANGE footer + RFC 먼저 | | hot fix | small PR, fast-track review, label `hotfix` | | cosmetic only | label `chore`, rubber-stamp review | **기본값**: 매 small (<300 LOC), single-purpose, conventional commit title, draft 시작 → ready when CI green → squash-merge. ## 🔗 Graph - 부모: [[Code-Review]] - 변형: [[Trunk-Based-Development]] - 응용: [[CI CD]] · [[GitHub-Actions]] - Adjacent: [[Conventional-Commits]] · [[Claude-Code]] · [[Refactoring_Best_Practices]] ## 🤖 LLM 활용 **언제**: PR description 초안, conventional commit message generation, first-pass review (typo / obvious bug / style). **언제 X**: architectural decision, security-sensitive review, business-logic correctness — LLM 의 surface false confidence, 매 human reviewer 의 final word. ## ❌ 안티패턴 - **Mega PR**: 1000+ LOC, multi-concern → reviewer 의 rubber-stamp, bugs slip. - **Ghost PR**: open PR, no description → reviewer 의 reverse-engineer intent. - **Drive-by review**: "LGTM" without reading diff. - **Force-push after review**: lose review thread context — prefer fixup commits, squash on merge. - **Branch from feature branch (not main)**: stacked dependency hell unless using Graphite. ## 🧪 검증 / 중복 - Verified (GitHub Docs 2026, Conventional Commits 1.0, Microsoft Code Review study 2013, Google Eng Practices). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — full PR best practices with AI review automation |