Small vs Big Pull Request #
Ada anggapan yang sangat umum di tim engineering: semakin banyak kode yang diselesaikan dalam satu PR, semakin produktif developernya. Logikanya terasa masuk akal — lebih banyak pekerjaan terselesaikan, lebih sedikit overhead koordinasi. Tapi anggapan ini keliru secara fundamental, dan dampaknya nyata: review yang tidak efektif, bug yang lolos, bottleneck yang melambat, dan frustrasi yang terakumulasi di kedua sisi — author maupun reviewer.
Ukuran PR bukan soal preferensi personal atau gaya kerja. Ia adalah keputusan arsitektural tentang bagaimana perubahan dikomunikasikan, divalidasi, dan diintegrasikan ke dalam codebase. Keputusan ini berdampak langsung pada kualitas review, kecepatan delivery, kemudahan rollback, dan kesehatan kolaborasi tim. Artikel ini membahas mengapa PR kecil hampir selalu lebih baik, kapan PR besar memang tidak terhindarkan, dan bagaimana strategi konkret untuk memecah pekerjaan besar menjadi PR yang bisa direview dengan efektif.
Apa yang Sebenarnya Terjadi saat Reviewer Membaca PR Besar #
Sebelum membahas strategi, perlu dipahami dulu apa yang terjadi di sisi reviewer ketika menghadapi PR besar. Ini bukan soal malas atau tidak profesional — ini soal bagaimana kognisi manusia bekerja.
Saat membaca PR dengan 50 baris perubahan, reviewer bisa membangun model mental yang lengkap tentang apa yang berubah, mengapa, dan apa dampaknya. Mereka bisa mendeteksi asumsi yang salah, edge case yang terlewat, atau pendekatan yang tidak konsisten dengan pola yang ada di sistem.
Saat membaca PR dengan 800 baris perubahan di 15 file, sesuatu yang berbeda terjadi:
Efek kognitif pada reviewer saat ukuran PR bertambah:
PR 50 baris → Working memory cukup → model mental lengkap
Reviewer menemukan: bug logika, edge case, design issue
PR 200 baris → Working memory mulai terbatas → model mental parsial
Reviewer menemukan: bug yang jelas, masalah lokal
Mulai melewatkan: konsistensi arsitektur, interaksi antar komponen
PR 500 baris → Working memory kewalahan → review terfragmentasi
Reviewer menemukan: masalah yang sangat jelas
Melewatkan: bug halus, asumsi implisit, dampak tidak langsung
PR 1000+ baris → Fatigue → approval tanpa pemahaman penuh
"LGTM" karena tidak mungkin memahami seluruhnya
PR masuk ke main dengan review yang hampir tidak bermakna
Ini bukan kelemahan reviewer — ini adalah batas kapasitas kognitif manusia yang tidak bisa dihindari. PR yang besar secara struktural mencegah review yang bermakna.
Dampak Ukuran PR terhadap Seluruh Proses #
Ukuran PR bukan hanya mempengaruhi kualitas review. Ia mempengaruhi hampir setiap aspek dari siklus development.
graph LR
A[Ukuran PR] --> B[Waktu Review]
A --> C[Kualitas Review]
A --> D[Risiko saat Merge]
A --> E[Kemudahan Rollback]
A --> F[Merge Conflict]
B --> |PR besar = lebih lama| G[Delivery Lambat]
C --> |PR besar = lebih lemah| H[Bug Lolos ke Produksi]
D --> |PR besar = risiko lebih tinggi| I[Insiden Produksi]
E --> |PR besar = sulit| J[Recovery Lambat]
F --> |PR besar = lebih banyak| K[Rework Tinggi]Waktu Review #
PR besar membutuhkan waktu review yang lebih lama — dan waktu itu tidak linear. Sebuah studi internal dari beberapa perusahaan teknologi menunjukkan pola yang konsisten: review yang optimal terjadi di bawah 400 baris perubahan. Di atas itu, efektivitas review menurun drastis sementara waktu yang dibutuhkan terus bertambah.
Hubungan ukuran PR dengan waktu dan kualitas review:
< 100 baris: Review selesai dalam 15–30 menit. Komentar berkualitas tinggi.
100–300 baris: Review selesai dalam 30–60 menit. Komentar masih fokus.
300–500 baris: Review butuh 1–2 jam. Energi mulai habis di tengah jalan.
500–800 baris: Review kerap ditunda ("nanti kalau ada waktu lebih").
> 800 baris: Review sering berakhir dengan LGTM tanpa benar-benar dibaca,
atau PR menganggur berhari-hari karena tidak ada yang mau mulai.
Feedback Loop #
PR kecil memperpendek feedback loop — waktu antara “kode selesai ditulis” dan “kode di-merge ke main”. PR besar memperpanjangnya, dan setiap hari yang berlalu membuat konteks makin basi.
gantt
title Perbandingan feedback loop: Small PR vs Big PR
dateFormat HH:mm
axisFormat %H:%M
section Small PR
Tulis kode :a1, 00:00, 2h
Review :a2, after a1, 1h
Revisi :a3, after a2, 30m
Merge :milestone, after a3, 0m
section Big PR
Tulis kode :b1, 00:00, 8h
Menunggu reviewer :b2, after b1, 4h
Review sesi 1 :b3, after b2, 2h
Revisi besar :b4, after b3, 3h
Review sesi 2 :b5, after b4, 2h
Revisi minor :b6, after b5, 1h
Merge :milestone, after b6, 0mMerge Conflict #
PR yang lama tidak di-merge adalah PR yang terus-menerus bergerak menjauhi main. Semakin lama PR terbuka, semakin besar kemungkinan terjadi merge conflict dengan PR lain yang sudah di-merge duluan. Merge conflict berarti rework — dan rework berarti waktu yang terbuang.
Rollback #
Ketika sebuah perubahan menyebabkan masalah di produksi, kemampuan rollback yang cepat adalah perbedaan antara insiden kecil dan insiden besar. PR yang kecil dan terfokus mudah di-revert — satu PR, satu tujuan, satu revert. PR besar yang mencampur beberapa perubahan tidak bisa di-revert sebagian — kamu harus revert semua atau tidak sama sekali.
Definisi “Kecil”: Bukan Soal Angka #
“Kecil” dalam konteks PR bukan threshold absolut — bukan “di bawah 300 baris” atau “di bawah 5 file”. Definisi yang lebih berguna adalah apakah satu reviewer bisa membangun model mental yang lengkap tentang PR ini dalam satu sesi review tanpa kehilangan konteks.
Dengan definisi ini, beberapa hal bisa mempengaruhi apakah PR terasa “kecil”:
Faktor yang membuat PR terasa lebih besar dari ukurannya:
→ Perubahan di domain yang tidak familiar bagi reviewer
300 baris di area yang reviewer tidak pernah sentuh = terasa seperti 1000 baris
→ Banyak file yang saling bergantung dengan cara yang tidak jelas
Perubahan di A mempengaruhi B yang mempengaruhi C — tapi tidak jelas dari diff
→ Tidak ada deskripsi yang membantu reviewer membangun konteks
Reviewer harus reverse-engineer intent dari kode
→ Campuran refactor dan behavior change
Reviewer tidak tahu mana perubahan yang harus diprioritaskan
Faktor yang membuat PR terasa lebih kecil dari ukurannya:
→ Deskripsi yang sangat baik — reviewer sudah punya model mental sebelum baca diff
→ Perubahan di satu domain yang reviewer sudah familiar
→ Commit yang terstruktur baik — bisa direview commit per commit
→ Perubahan yang sangat lokal dan tidak memiliki side effect ke komponen lain
Kapan Big PR Memang Tidak Terhindarkan #
Ada situasi di mana PR besar bukan karena kurangnya disiplin, tapi karena sifat perubahan itu sendiri yang tidak bisa dipecah tanpa kehilangan koherensi.
Situasi di mana big PR legitimate:
1. Migrasi framework atau major refactor
→ Perubahan yang saling bergantung satu sama lain
→ Memecah bisa meninggalkan codebase dalam state yang tidak konsisten
2. Penambahan fitur yang atomic
→ Fitur yang hanya bermakna ketika semua komponen sudah ada
→ Contoh: sistem pembayaran baru yang melibatkan gateway, webhook, dan UI sekaligus
3. Perubahan schema database yang berdampak luas
→ Schema change + migration + update semua query yang terdampak
4. Security patch yang membutuhkan perubahan di banyak tempat
→ Tidak bisa di-merge setengah-setengah karena security hole tetap ada
5. Generated code atau automated changes
→ Perubahan yang di-generate oleh tool (protobuf, OpenAPI, dsb)
→ Ukurannya besar tapi tidak perlu direview baris per baris
Big PR yang legitimate tetap membutuhkan persiapan ekstra: deskripsi yang lebih detail, panduan review yang jelas (bagian mana yang krusial, bagian mana yang generated/boilerplate), dan kemungkinan review session bersama daripada async review. “Big PR tidak bisa dihindari” bukan berarti “big PR boleh dibuka tanpa persiapan”.
Strategi Memecah PR Besar #
Hambatan terbesar untuk membuat PR kecil bukan teknis — ini mental. “Kalau fiturnya belum lengkap, bagaimana bisa di-merge?” Ini adalah pertanyaan yang valid, dan ada beberapa strategi untuk menjawabnya.
Strategi 1: Pisahkan Refactor dari Feature #
Ini adalah pemisahan paling fundamental dan paling sering diabaikan. Refactor dan behavior change adalah dua jenis perubahan yang sangat berbeda dan harus direview dengan cara yang berbeda.
flowchart TD
A[Feature Baru yang Membutuhkan Refactor] --> B[PR 1: Refactor]
B --> C{Behavior berubah?}
C -- Tidak --> D[Merge ✓]
D --> E[PR 2: Feature]
E --> F[Merge ✓]
C -- Ya --> G[Pisah lagi]Contoh pemisahan yang benar:
Task: Tambahkan fitur export laporan ke CSV
(Butuh refactor service layer terlebih dahulu)
✗ Cara yang salah — satu PR:
PR: "Add CSV export feature"
- Refactor ReportService dari class ke function
- Tambah method exportToCSV()
- Tambah endpoint /reports/export
- Tambah test untuk semua di atas
✓ Cara yang benar — dua PR:
PR 1: "refactor(report): convert ReportService to functional style"
- Refactor murni, tidak ada behavior change
- Test yang ada tetap lulus (behavior tidak berubah)
- Reviewer bisa fokus: "apakah refactor ini benar?"
PR 2: "feat(report): add CSV export endpoint"
- Menambahkan method dan endpoint baru
- Reviewer bisa fokus: "apakah implementasinya benar?"
Strategi 2: Feature Flag untuk Merge Inkremental #
Feature flag memungkinkan kode di-merge ke main sebelum fitur siap diaktifkan untuk user. Ini adalah salah satu teknik paling powerful untuk menghindari long-lived branch dan PR besar.
Alur development dengan feature flag:
Week 1 — PR 1: Infrastructure
├── Tambah database schema baru (migration)
├── Tambah repository layer
└── Feature flag: ENABLE_NEW_PAYMENT = false (belum aktif)
→ Merge ke main, tidak ada impact ke user
Week 2 — PR 2: Core Logic
├── Implementasi payment service
├── Unit test untuk service
└── Masih di balik feature flag
→ Merge ke main, tidak ada impact ke user
Week 3 — PR 3: API Layer
├── Tambah endpoint baru
├── Integration test
└── Masih di balik feature flag
→ Merge ke main, QA testing di staging
Week 4 — PR 4: Activation
├── Aktifkan feature flag untuk 10% user (canary release)
└── Monitor metric
→ Rollout bertahap
Hasilnya:
→ Tidak ada PR yang lebih dari 300-400 baris
→ Setiap PR bisa direview dengan fokus
→ Main branch selalu dalam state yang bisa di-deploy
→ Rollback semudah mematikan feature flag
Strategi 3: Stacked PR (PR Berantai) #
Stacked PR adalah teknik di mana satu PR bergantung pada PR sebelumnya — PR 2 di-branch dari PR 1, bukan dari main. Ini memungkinkan development yang linear pada fitur yang memiliki dependensi sequential.
gitGraph
commit id: "main"
branch pr-1-schema
checkout pr-1-schema
commit id: "add users schema"
commit id: "add migration"
checkout main
merge pr-1-schema id: "Merge PR 1"
branch pr-2-service
checkout pr-2-service
commit id: "add UserService"
commit id: "add unit tests"
checkout main
merge pr-2-service id: "Merge PR 2"
branch pr-3-api
checkout pr-3-api
commit id: "add /users endpoint"
commit id: "add integration tests"
checkout main
merge pr-3-api id: "Merge PR 3"Cara kerja stacked PR:
PR 1: "feat(auth): add users and sessions schema"
→ Branch dari main
→ Berisi: migration, schema definition
→ Di-merge dulu
PR 2: "feat(auth): implement UserService"
→ Branch dari branch PR 1 (sebelum PR 1 di-merge)
→ Reviewer bisa review PR 2 paralel dengan PR 1
→ Setelah PR 1 di-merge, rebase PR 2 ke main
PR 3: "feat(auth): add user registration endpoint"
→ Branch dari branch PR 2
→ Reviewer mereview hanya perubahan PR 3 (bukan PR 1 + PR 2)
Catatan penting untuk stacked PR:
→ Jika PR 1 memerlukan perubahan besar, PR 2 dan PR 3 perlu di-rebase
→ Tools seperti ghstack (GitHub) atau Graphite memudahkan manajemen stacked PR
→ Cocok untuk tim yang sudah familiar dengan Git workflow
Strategi 4: Spike Branch untuk Eksplorasi #
Ketika scope pekerjaan belum jelas, membuat spike branch untuk eksplorasi sebelum commit ke PR yang sebenarnya adalah pilihan yang lebih baik daripada langsung membuat PR besar yang ternyata harus diubah total.
Spike → Draft PR → PR siap review:
Spike branch:
→ Eksplorasi bebas, tidak perlu clean
→ Tidak ada ekspektasi review
→ Tujuan: memahami masalah dan menemukan pendekatan
Draft PR:
→ Setelah pendekatan ditemukan, buat PR dengan deskripsi
→ Buka sebagai Draft untuk diskusi awal
→ Minta feedback tentang arah sebelum implementasi penuh
PR siap review:
→ Implementasi bersih berdasarkan hasil spike dan feedback Draft PR
→ Dipecah menjadi PR kecil berdasarkan pemahaman yang sudah ada
Tanda-tanda PR Perlu Dipecah #
Ada beberapa sinyal yang menunjukkan bahwa sebuah PR sudah terlalu besar dan perlu dipecah:
Sinyal bahwa PR perlu dipecah:
✗ Diff lebih dari 400 baris dan masih terus bertambah
✗ Judul PR tidak bisa diringkas dalam satu kalimat yang spesifik
✗ PR menyentuh lebih dari 2-3 domain yang berbeda
✗ Ada refactor dan feature change yang dicampur
✗ Butuh meeting khusus untuk menjelaskan PR ke reviewer
✗ Reviewer meminta clarification tentang konteks yang seharusnya ada di deskripsi
✗ PR sudah terbuka lebih dari 3 hari tanpa kemajuan review
✗ Ada komentar "ini terlalu besar untuk direview sekarang"
Pertanyaan yang membantu memutuskan:
→ Bisakah bagian ini di-merge sendiri tanpa menunggu bagian lain?
→ Apakah reviewer perlu memahami seluruh PR untuk me-review satu bagian?
→ Jika PR ini di-revert, apakah semua perubahan harus ikut di-revert?
Perbandingan Lengkap: Small vs Big PR #
┌─────────────────────┬────────────────────────┬──────────────────────────┐
│ Aspek │ Small PR │ Big PR │
├─────────────────────┼────────────────────────┼──────────────────────────┤
│ Waktu review │ 15–60 menit │ 1–4+ jam (atau ditunda) │
│ Kualitas review │ Tinggi, fokus │ Menurun seiring ukuran │
│ Feedback loop │ Cepat (jam/hari) │ Lambat (hari/minggu) │
│ Merge conflict │ Jarang │ Sering │
│ Rollback │ Mudah dan tepat │ Sulit, semua atau tidak │
│ Blast radius jika bug│ Kecil, terlokalisasi │ Besar, menyebar │
│ Dokumentasi │ Jelas per perubahan │ Konteks bercampur │
│ Onboarding │ Mudah dipelajari │ Sulit dipahami historis │
│ Motivasi reviewer │ Tinggi │ Rendah (capek sebelum │
│ │ │ mulai) │
│ Deployment risk │ Rendah │ Tinggi │
└─────────────────────┴────────────────────────┴──────────────────────────┘
Anti-Pattern yang Harus Dihindari #
✗ Anti-pattern 1: "Biar sekalian"
Menambahkan perubahan yang tidak terkait ke PR yang sedang berjalan
karena "sudah buka file ini anyway". Setiap penambahan memperluas scope
dan memperpanjang review.
✓ Buat PR terpisah, bahkan untuk perubahan kecil yang tidak terkait.
────────────────────────────────────────────────────────────────────────────
✗ Anti-pattern 2: Long-lived branch
Branch yang hidup berminggu-minggu tanpa di-merge karena "belum selesai".
Semakin lama branch hidup, semakin besar PR-nya, semakin banyak merge
conflict, semakin sulit direview.
✓ Gunakan feature flag atau stacked PR untuk merge inkremental.
────────────────────────────────────────────────────────────────────────────
✗ Anti-pattern 3: Campur refactor dan behavior change
Reviewer tidak bisa memisahkan mana perubahan yang "harusnya tidak
mengubah behavior" dan mana yang "memang mengubah behavior".
Ini membuat review jauh lebih sulit.
✓ PR 1 untuk refactor (test yang ada harus tetap lulus).
PR 2 untuk behavior change atau feature baru.
────────────────────────────────────────────────────────────────────────────
✗ Anti-pattern 4: "Nanti kalau sudah lengkap baru PR"
Menunggu fitur 100% selesai sebelum membuka PR. Hasilnya PR monster
dengan ribuan baris yang tidak mungkin direview dengan efektif.
✓ PR adalah alat kolaborasi, bukan hanya alat merge.
Buka Draft PR lebih awal untuk mendapat feedback arah lebih cepat.
────────────────────────────────────────────────────────────────────────────
✗ Anti-pattern 5: Approve PR besar karena kelelahan
Reviewer meng-approve PR 1000 baris bukan karena sudah review dengan baik,
tapi karena tidak sanggup lagi membacanya. Ini adalah false sense of security
yang paling berbahaya.
✓ Jika PR terlalu besar untuk direview dengan baik, katakan itu.
Minta author memecahnya daripada approve tanpa membaca.
Checklist Review Small vs Big PR #
SEBELUM MEMBUKA PR:
□ Apakah PR ini bisa diringkas dalam satu kalimat yang spesifik?
□ Apakah ada refactor dan behavior change yang dicampur? → pisahkan
□ Apakah PR menyentuh lebih dari 2-3 domain? → pertimbangkan pecah
□ Apakah ada bagian yang bisa di-merge sendiri sebelum yang lain selesai?
□ Jika > 400 baris: apakah sudah dipikirkan cara memecahnya?
SAAT PR SUDAH TERLALU BESAR:
□ Identifikasi bagian yang paling independent untuk dipecah duluan
□ Pisahkan refactor murni ke PR terpisah
□ Pertimbangkan feature flag untuk merge inkremental
□ Pertimbangkan stacked PR jika ada dependensi sequential
□ Tambahkan panduan review di deskripsi: "mulai dari sini", "bagian ini generated"
SEBAGAI REVIEWER YANG MENERIMA PR BESAR:
□ Jangan approve hanya karena lelah membaca
□ Komunikasikan ke author: "PR ini terlalu besar untuk direview efektif"
□ Bantu author mengidentifikasi cara memecahnya jika dia tidak tahu caranya
□ Jika big PR legitimate (migrasi, generated code), tandai bagian yang perlu
perhatian ekstra vs bagian yang bisa di-skim
Ringkasan #
- Ukuran PR mempengaruhi kualitas review secara langsung — semakin besar PR, semakin menurun kemampuan reviewer membangun model mental yang lengkap. Ini bukan soal kemampuan reviewer, tapi keterbatasan kognitif manusia yang tidak bisa dihindari.
- Small PR bukan berarti lambat — justru sebaliknya. PR kecil yang cepat di-merge menghasilkan delivery lebih cepat dari PR besar yang menganggur berhari-hari menunggu review.
- “Kecil” didefinisikan oleh kemampuan review, bukan angka absolut — pertanyaannya bukan “apakah kurang dari 300 baris?”, tapi “apakah reviewer bisa membangun model mental yang lengkap dalam satu sesi?”
- Pisahkan refactor dari behavior change — ini adalah pemisahan paling fundamental. Refactor dan feature adalah dua jenis review yang berbeda dan tidak bisa dilakukan bersamaan dengan efektif.
- Feature flag memungkinkan merge sebelum fitur selesai — kode bisa di-merge ke main tanpa diaktifkan ke user. Ini menghilangkan kebutuhan long-lived branch yang berujung PR besar.
- Stacked PR untuk perubahan sequential — PR yang saling bergantung bisa dibuat dalam rantai, memungkinkan review paralel dan merge bertahap.
- Long-lived branch adalah akar masalah — branch yang hidup berminggu-minggu menghasilkan PR monster dengan merge conflict dan konteks yang sudah basi.
- Big PR yang legitimate tetap butuh persiapan ekstra — deskripsi lebih detail, panduan review yang jelas, dan kemungkinan review session sinkron.
- Jangan approve PR besar karena kelelahan — ini adalah false sense of security yang paling berbahaya. Lebih baik minta author memecahnya daripada approve tanpa membaca dengan benar.
- Budaya small PR dibangun bersama — ini bukan tanggung jawab satu orang. Tim perlu sepakat bahwa memecah PR adalah investasi, bukan hambatan.