Pada akhirnya, Anda akan tetap menggunakan `git bisect`
(kevin3010.github.io)- Konsep pencarian biner (binary search) tidak hanya dipakai dalam soal wawancara, tetapi juga dimanfaatkan dalam Git sebagai alat pengembangan nyata
- Di lingkungan monorepo berskala besar, ketika pengujian tiba-tiba gagal, ada situasi di mana penyebabnya sulit dilacak hanya dari log
- Seorang rekan menentukan commit baik dan commit buruk lalu menjalankan pencarian otomatis dengan
git bisect, sehingga berhasil menemukan dengan tepat commit bermasalah tempat bug mulai muncul - Pada setiap tahap, skrip dijalankan untuk mengklasifikasikan commit secara otomatis berdasarkan hasil pengujian, lalu mengidentifikasi commit pertama yang gagal
- Dengan memanfaatkan prinsip pencarian biner,
git bisectadalah alat yang sangat kuat untuk melacak penyebab bug dengan cepat di codebase berskala besar
Algoritme dan kasus nyata
- Algoritme pencarian biner (binary search) tidak berhenti sebagai soal wawancara sederhana, tetapi juga menjadi prinsip inti dalam alat debugging nyata
git bisectdapat digunakan sebagai alat yang memakai pencarian biner untuk menemukan “commit pertama yang memperkenalkan bug (first bad commit)”- Bekerja dengan prinsip yang mirip dengan soal “First Bad Version” di Leetcode
Situasi masalah di lingkungan kerja nyata
- Dalam lingkungan yang menggunakan monorepo besar, ratusan hingga ribuan commit bisa terjadi setiap hari
- Penyebab kegagalan pengujian tertentu sulit dilacak hanya dari log
- Penyebab kegagalan adalah perubahan string dalam file konfigurasi untuk mendapatkan token yang dibutuhkan untuk pemanggilan jarak jauh, sehingga mengacu ke akun lain dan membuat pengujian gagal
- Perubahan ini lolos pengujian integrasi, tetapi sebenarnya menimbulkan masalah, dan sulit menemukan pada titik mana di antara begitu banyak commit hal itu mulai terjadi
Menyelesaikan masalah dengan git bisect
- Seorang rekan dari tim lain menggunakan perintah
git bisectuntuk dengan cepat mengidentifikasi commit bermasalah- Setelah menentukan commit baik (good) dan commit buruk (bad), alat ini secara otomatis melakukan checkout ke commit-commit di tengah, menjalankan pengujian, dan mempersempit sumber masalah
- Setiap eksekusi pengujian memang memerlukan waktu, tetapi pada akhirnya berhasil menemukan commit yang tepat yang memperkenalkan masalah
- Setelah commit tersebut dibatalkan, semua pengujian kembali normal
Proses menjalankan git bisect
- Contoh riwayat commit
- Commit 1: commit awal (normal)
- Commit 2: refactoring (normal)
- Commit 3: bug diperkenalkan (muncul error)
- Commit 4~10: perubahan nonfungsional (error tetap ada)
- Contoh perintah eksekusi
git bisect start git bisect bad HEAD git bisect good HEAD~9 git bisect run ./test_script.sh - Skrip pengujian (
test_script.sh) mengembalikan 0 saat sukses, dan kode abnormal saat gagal git bisectsecara otomatis melakukan checkout ke commit di tengah dan menjalankan skrip pengujian,
lalu mengidentifikasi commit buruk pertama berdasarkan titik saat pengujian mulai gagal- Dari hasil output, commit
b982ed9373fe235fe61c74b15faf264bc7142398terkonfirmasi sebagai commit bug pertama
Kesimpulan
git bisectadalah alat praktis yang menerapkan prinsip pencarian biner pada penelusuran riwayat kode- Bahkan dalam repositori besar atau riwayat perubahan yang kompleks, alat ini dapat dengan cepat melacak kapan bug mulai diperkenalkan
- Jika dikombinasikan dengan otomatisasi pengujian, debugging yang stabil tetap memungkinkan bahkan di codebase berskala besar
2 komentar
Karena masalah-masalah seperti ini, kami menggunakan TBD (trunk-based development).
Komentar Hacker News
Dulu saat bekerja di codebase raksasa yang hampir tidak punya test coverage dan abstraksinya berantakan,
git bisectnyaris menjadi satu-satunya alat yang benar-benar bergunaKodenya terlalu rumit sehingga mustahil melacak bug secara logis, jadi jauh lebih mudah mencari commit mana yang memunculkan masalah
Namun, di codebase berkualitas tinggi, bisect tidak terlalu dibutuhkan. Tiap komponen bisa diuji secara independen, dan observability-nya juga bagus sehingga jelas harus melihat ke mana
git bisectsama sekali tidak pernah menjadi alat yang tidak perlu. Bukan cuma untuk menemukan bug, tetapi juga membantu memahami mengapa bug itu munculJika proyek memiliki commit message yang baik, lewat bisect kita bisa memahami konteks commit lama dan mencerminkan isinya ke commit perbaikan bug. Siklus seperti ini memperkuat budaya commit itu sendiri
Mustahil menelusurinya secara langsung, tetapi setelah menulis skrip bisect dan menjalankannya sekitar 30 menit, saya bisa menemukan commit penyebabnya dengan tepat
git bisectawalnya diperkenalkan untuk mencari regression di kernel LinuxBahkan untuk hal seperti driver hardware yang tidak bisa diuji, pengguna biasa jadi bisa melakukan bisect pada kernel sendiri dan mengidentifikasi commit bermasalah
Dulu orang harus mengirim email ke developer untuk meminta bantuan, tetapi sekarang pengguna bisa mempersempit masalah sendiri
Misalnya untuk melacak cakupan data yang salah diproses, atau untuk menilai apakah “ini bug atau fitur”
Misalnya saat pelanggan mengalami masalah di versi 6 tahun lalu, kita bisa memeriksa apakah upgrade ke versi 4 tahun lalu akan menyelesaikannya
Atau saat kode sudah banyak direfaktor, kita juga bisa mengetahui apakah perbaikan bug itu memang disengaja atau hanya kebetulan
git bisectsangat hebat saat bekerja dengan baik, tetapi tidak berarti bisa menemukan semua bugAda bug yang belum menimbulkan gejala saat diperkenalkan, lalu baru terlihat kemudian karena perubahan lain
Dalam kasus seperti ini, asumsi bisect—bahwa bug hanya muncul satu kali di antara commit baik dan commit buruk—menjadi tidak berlaku
Commit yang tidak bisa diuji bisa di-
skip, tetapi jika itulah commit bermasalah, hasilnya menjadi ambiguBaru-baru ini saya pertama kali memakai
git bisectdengan serius, dan rasanya hampir seperti sihirAda dua fungsi dengan nama yang sama, lalu saat pekerjaan formatting kode, import fungsi yang benar malah dihapus sehingga menimbulkan masalah
Saya sudah meninjau kodenya berkali-kali, tetapi sama sekali tidak tahu penyebabnya sampai bisect menunjukkan commit bermasalah
Biasanya saya sudah tahu kisaran file atau fungsi tempat bug muncul, jadi saya tidak terlalu sering memakai bisect
Sebagai gantinya saya melacak riwayat perubahan fungsi tertentu dengan perintah
git log -L :func_name:path/to/file.cDiperlukan pengaturan
.gitattributes.gitattributes. Responsnya adalah ingin tahu lebih lanjut konfigurasi seperti apa yang dibutuhkangit log -Lkurang kuat. Sulit melacak versi tertentu di antara fungsi overload dengan nama yang sama.gitattributes, memakaigit log -Suntuk mencari commit yang memuat string tertentu juga bisa menjadi caraDi skrip pengujian, ada baiknya mengetahui exit code 125
Jika hasil pengujian tidak bisa ditentukan, seperti saat build gagal, mengembalikan 125 akan membuat bisect melewati commit tersebut
Hal terkait ini saya rangkum di artikel blog saya
git bisect --first-parentakan bergunaDengan begitu kita bisa cepat menemukan “PR mana yang memperkenalkan bug”, lalu setelah itu menjalankan bisect yang lebih detail sekali lagi di branch tersebut
Saat muncul flaky test, bisect benar-benar menunjukkan kekuatannya
Jika karena race condition kita harus menjalankan tes ratusan ribu kali untuk yakin, menjalankan skrip bisect di background bisa menjadi solusi yang realistis
Baru-baru ini saya menemukan penyebab bug dengan bisect di proyek pemutar musik berbasis Svelte (lets-make-sweet-music.com)
Tidak ada tes maupun log error, dan karena update
dependabotjumlah commit menjadi banyak sehingga sulit dilacakBerkat bisect saya menemukan commit bermasalah, dan penyebabnya adalah file pengganti yang saya pakai ternyata tidak mengimplementasikan fitur multi-binding event
Jika commit dijaga tetap kecil, penyebab masalah yang ditemukan lewat bisect bisa dipersempit dengan cepat
Seseorang bilang bahwa keharusan mempelajari binary search untuk wawancara itu dipaksakan, tetapi
git bisectadalah contoh bagus yang menunjukkan konsep itu di dunia nyataNamun tidak perlu mengimplementasikannya sendiri. Di sebagian besar bahasa, itu sudah tersedia sebagai library standar
Saat menghitung indeks tengah, memakai
(low + high) / 2bisa menyebabkan overflowIni latihan terbaik untuk melatih cara berpikir berbasis invariant
Di Git, selain bisect juga ada alat penelusuran kode hebat seperti
log -L,log -S, danblameSaya pernah menulis artikel blog tentang topik ini sebelumnya