Dev Study
← 解説「小さいPR — 差分が小さいほどレビューは速く深くなる」に戻る

サンプルコードで身につける: 小さいPR — 差分が小さいほどレビューは速く深くなる

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1大きいPRと小さいPRのレビューのされ方

差分が大きいほどレビューは浅くなる、というのは実務でよく知られた現象です。小さい PR は数分で読めるので細部まで指摘が入りますが、巨大な PR は読み切れず形式的な承認になりがちです。品質を上げたいなら PR を小さくするのが近道です。

# ── PR の大きさとレビューの質(実務でよく起きること)──

# 小さい PR(〜数百行)
#   ・レビュアーは数分〜十数分で読み切れる
#   ・ロジックの誤りや命名まで細かい指摘が入る
#   ・すぐレビューしてもらえるのでマージまでが速い

# 大きい PR(数千行)
#   ・読むのに数時間かかり、レビューが後回しにされる
#   ・全体を追い切れず「ざっと見て LGTM」になりがち
#   ・= 一番バグが混ざりやすい PR ほどチェックが甘くなる

# 「10行の PR には10件の指摘が付き、
#   1000行の PR には LGTM が付く」という有名なジョークもある

21つの機能を3つのPRに刻む

「一覧画面の追加」のような大きめの機能は、レイヤーや段階で刻んで順番に PR を出します。各 PR が単体でマージ可能な完成品になるように切るのがコツです。画面から呼ばれていないサービス層だけを先にマージしても、アプリは壊れません。

# 「ユーザー一覧画面の追加」を3つの PR に刻む例

# PR 1: サービス層のみ(画面はまだ無い)
git switch -c feature/user-api main
#   user-api.service.ts + テストだけを作って PR に
#   → どこからも呼ばれていないのでマージしてもアプリは壊れない

# PR 2: 一覧画面の骨組み(PR 1 のマージ後に着手)
git switch main && git pull
git switch -c feature/user-list
#   user-list コンポーネントでサービスを呼び、一覧を表示

# PR 3: 検索機能(PR 2 のマージ後に着手)
git switch main && git pull
git switch -c feature/user-search
#   一覧に検索ボックスを追加

# 3つとも小さいのでレビューが速く、途中経過も main に残っていく

3リファクタリングと機能追加を混ぜない

名前変更やファイル移動と新機能を同じ PR に入れると、大量の機械的な差分に本質的な変更が埋もれてしまいます。先にリファクタリングだけの PR を出してマージし、そのあときれいになったコードの上に機能追加の PR を重ねるのが定石です。

# ── 悪い例: 1つの PR に混ぜる ──
#   ・UserData → User へのリネーム(50ファイルに波及)
#   ・検索機能の追加(3ファイル)
#   → レビュアーは 53 ファイルの差分から
#     「本当に読むべき3ファイル」を探すはめになる

# ── 良い例: 2つの PR に分ける ──

# PR 1: リファクタリングのみ
git switch -c refactor/rename-user-model main
#   「リネームだけ。動作の変更なし」と説明文に書く
#   → 機械的な変更だと分かるので、レビューはすぐ終わる

# PR 2: 機能追加のみ(PR 1 のマージ後)
git switch -c feature/user-search main
#   → 3ファイルの本質的な差分だけをじっくり読んでもらえる

4自分のPRの差分量を確認する

PR を出す前に、マージ先との差分量を数字で確認する習慣をつけましょう。git diff --stat でファイル数と行数が一目で分かります。数百行を超えていたら、分割できないか一度立ち止まって考えるサインです。

# マージ先(main)との差分の統計を見る
git diff --stat main
# => src/app/user-list/user-list.ts   |  48 +++++++
#    src/app/user-list/user-list.html |  22 ++++
#    src/app/user-api.service.ts      |  35 ++++++
#    3 files changed, 105 insertions(+), 0 deletions(-)

# 変更したファイルの一覧だけをさっと見る
git diff --name-only main

# 目安(チームにより異なる):
#   〜200行程度  : 読みやすい理想的なサイズ
#   数百行       : 分割を検討し始めるライン
#   1000行超     : よほどの理由がなければ分ける
#   ※ 自動生成ファイルやリネームは例外として説明文で断る

5前のPRを待たずに積み上げる — baseブランチの指定

PR 1 のレビュー待ちの間に続きを作りたいときは、PR 1 のブランチから次のブランチを切り、PR のマージ先(base)を PR 1 のブランチに指定します。こうすると PR 2 の画面には自分の追加分だけが差分として表示されます。

# PR 1(feature/user-api)がレビュー待ちの間に、続きを作る

# 1. PR 1 のブランチから続きのブランチを切る
git switch feature/user-api
git switch -c feature/user-list

# 2. 作業して push したら、base を PR 1 のブランチにして PR を作る
git push -u origin feature/user-list
gh pr create --base feature/user-api \
  --title "ユーザー一覧画面の骨組みを追加"

# base を main のままにすると PR 1 の差分まで混ざって表示されるが、
# base を feature/user-api にすれば「自分の追加分」だけが差分になる

# 3. PR 1 がマージされたら、PR 2 の base を main に変更する
gh pr edit --base main