14 poin oleh GN⁺ 2025-11-04 | 2 komentar | Bagikan ke WhatsApp
  • 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 bisect adalah 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 bisect dapat 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
Iklan

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 bisect untuk 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)
    Iklan
  • 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 bisect secara 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 b982ed9373fe235fe61c74b15faf264bc7142398 terkonfirmasi sebagai commit bug pertama

Kesimpulan

  • git bisect adalah 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

 
kandk 2025-11-04

Karena masalah-masalah seperti ini, kami menggunakan TBD (trunk-based development).

 
GN⁺ 2025-11-04
Komentar Hacker News
  • Dulu saat bekerja di codebase raksasa yang hampir tidak punya test coverage dan abstraksinya berantakan, git bisect nyaris menjadi satu-satunya alat yang benar-benar berguna
    Kodenya 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

    • Menurut saya git bisect sama sekali tidak pernah menjadi alat yang tidak perlu. Bukan cuma untuk menemukan bug, tetapi juga membantu memahami mengapa bug itu muncul
      Jika 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
    • Saya pernah menemukan bug dengan string aneh di sebuah program OSS. Kodenya C, dan penyebabnya adalah variabel yang tidak diinisialisasi
      Mustahil menelusurinya secara langsung, tetapi setelah menulis skrip bisect dan menjalankannya sekitar 30 menit, saya bisa menemukan commit penyebabnya dengan tepat
    • git bisect awalnya diperkenalkan untuk mencari regression di kernel Linux
      Bahkan 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
    • Jika tujuannya hanya memperbaiki bug, bisect mungkin tidak diperlukan. Tetapi ada kalanya kita perlu tahu sejak kapan bug itu ada
      Misalnya untuk melacak cakupan data yang salah diproses, atau untuk menilai apakah “ini bug atau fitur”
    • Kadang kita juga perlu tahu kapan bug itu diperbaiki
      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 bisect sangat hebat saat bekerja dengan baik, tetapi tidak berarti bisa menemukan semua bug
    Ada 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 ambigu

  • Baru-baru ini saya pertama kali memakai git bisect dengan serius, dan rasanya hampir seperti sihir
    Ada 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.c
    Diperlukan pengaturan .gitattributes

    • Ada yang bertanya soal pengaturan .gitattributes. Responsnya adalah ingin tahu lebih lanjut konfigurasi seperti apa yang dibutuhkan
    • Ada juga yang bilang mereka memakai bisect setiap hari. Workflow-nya benar-benar berbeda
    • Dalam kasus seperti C++ yang punya fungsi polimorfik, git log -L kurang kuat. Sulit melacak versi tertentu di antara fungsi overload dengan nama yang sama
    • Jika tidak ada .gitattributes, memakai git log -S untuk mencari commit yang memuat string tertentu juga bisa menjadi cara
  • Di 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

    • Pada repositori yang commit merge-nya menandai titik lulus CI, memakai git bisect --first-parent akan berguna
      Dengan 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

    • Dalam kasus seperti ini, sepertinya menerapkan pencarian biner Bayesian bisa sangat mengurangi jumlah pengujian yang diperlukan
  • 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 dependabot jumlah commit menjadi banyak sehingga sulit dilacak
    Berkat 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 bisect adalah contoh bagus yang menunjukkan konsep itu di dunia nyata
    Namun tidak perlu mengimplementasikannya sendiri. Di sebagian besar bahasa, itu sudah tersedia sebagai library standar

    • Menariknya, ada cerita bahwa meskipun binary search pertama kali diajukan pada 1940-an, implementasi tanpa bug baru muncul pada 1960-an
      Saat menghitung indeks tengah, memakai (low + high) / 2 bisa menyebabkan overflow
    • Secara pribadi saya rasa semua developer sebaiknya sekali mencoba mengimplementasikan binary search sendiri dalam bahasa dengan integer presisi arbitrer (misalnya Python)
      Ini latihan terbaik untuk melatih cara berpikir berbasis invariant
  • Di Git, selain bisect juga ada alat penelusuran kode hebat seperti log -L, log -S, dan blame
    Saya pernah menulis artikel blog tentang topik ini sebelumnya