---
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
<problem this solves; link to issue>

## 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 |
