Bisect

Mencari commit penyebab bug secara otomatis dengan pencarian biner git bisect run.

Daftar isi

Ketika sebuah bug dilaporkan dan penyebabnya tidak terlihat, pertanyaan yang paling berguna adalah commit mana yang pertama membawanya. Menjawabnya dengan membaca commit satu per satu boros, sedangkan git bisect menjawabnya dengan pencarian biner (binary search) yang membagi riwayat menjadi dua pada setiap langkah. Topik ini membahas alur manualnya, otomatisasi penuhnya melalui git bisect run, dan cara kembali dari keadaan pemeriksaan.

Pencarian biner pada riwayat#

Pencarian biner bekerja pada satu syarat, yaitu keadaan yang diketahui baik dan keadaan yang diketahui buruk. Git menguji commit di tengah keduanya, lalu mengganti salah satu batas sesuai jawaban, sehingga jumlah ujian yang diperlukan tumbuh secara logaritmik terhadap jumlah commit. Riwayat seribu commit cukup diuji sekitar sepuluh kali, bukan seribu kali.

Syarat kedua adalah perintah pengujian yang dapat menyatakan baik atau buruk secara pasti. Bentuknya sering sederhana, misalnya program berjalan tanpa error, atau sebuah berkas memuat keluaran yang benar. Siapkan riwayat tujuh commit yang menyisipkan bug pada tengahnya, lalu jalankan pencarian manual.

bash
# tanggal commit ditetapkan agar keluaran contoh dapat direproduksi secara persis
export GIT_AUTHOR_DATE="2026-11-01T09:00:00+07:00"
export GIT_COMMITTER_DATE="2026-11-01T09:00:00+07:00"
bash
rm -rf /tmp/lab-bisect
mkdir /tmp/lab-bisect
cd /tmp/lab-bisect
git init -b main
git config user.name "Budi"
git config user.email "[email protected]"
for i in 1 2 3 4 5 6 7; do
  if [ "$i" -ge 5 ]; then printf "Iterasi $i.\nBUG: pembagian nol.\n" > app.txt; else printf "Iterasi $i.\n" > app.txt; fi
  git add app.txt
  git commit -q -m "Iterasi $i"
done
git bisect start HEAD HEAD~6
text Keluaran
Initialized empty Git repository in /tmp/lab-bisect/.git/
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[bede1de7b09029405b4356c38fcad741fd7754df] Iterasi 4

Argumen git bisect start berbentuk buruk baik, yaitu HEAD sebagai ujung yang diketahui buruk dan HEAD~6 sebagai commit pertama yang diketahui baik. Git langsung berpindah ke commit tengah, yaitu Iterasi 3, dan menyatakan sisa langkah yang diperlukan.

Otomatisasi penuh dengan git bisect run#

Pada tiap langkah manual, pemeriksa menjalankan pengujian lalu menyatakan git bisect good atau git bisect bad. Apabila pengujian dapat dikemas menjadi perintah yang keluarannya menyatakan keadaan tersebut, seluruh langkah dapat diserahkan kepada git bisect run, dan pencarian berjalan tanpa penyelaan manusia.

bash
git bisect run sh -c '! grep -q BUG app.txt'
text Keluaran
running 'sh' '-c' ''\!' grep -q BUG app.txt'
Bisecting: 0 revisions left to test after this (roughly 1 step)
[bff6b475aa677a8617822730be0e97fddfd7d7d7] Iterasi 6
running 'sh' '-c' ''\!' grep -q BUG app.txt'
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[05abb1c3ec168fe8a1def14ea5a9eefa903eb993] Iterasi 5
running 'sh' '-c' ''\!' grep -q BUG app.txt'
05abb1c3ec168fe8a1def14ea5a9eefa903eb993 is the first bad commit
commit 05abb1c3ec168fe8a1def14ea5a9eefa903eb993
Author: Budi <[email protected]>
Date:   Sun Nov 1 09:00:00 2026 +0700

    Iterasi 5

 app.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
bisect found first bad commit

Kontrak perintah pengujinya lurus: keluaran nol berarti keadaan baik, keluaran bukan nol berarti buruk. Perintah sh -c '! grep -q BUG app.txt' mengembalikan nol ketika kata BUG tidak ditemukan, sehingga pengujian membalik syarat grep menjadi ujian kelayakan. Git memutar pengujian pada setiap tengah, dan baris is the first bad commit menampilkan jawaban akhirnya lengkap dengan metadata commit dan diff-nya, yaitu commit Iterasi 5 yang memang menyisipkan bug.

Alur manual untuk memahami langkahnya#

Otomatisasi run menyembunyikan pergerakannya, dan alur manual membuat setiap langkah terlihat. Perintah git bisect good atau git bisect bad menyatakan keadaan commit yang sedang diperiksa, lalu Git berpindah ke tengah berikutnya sampai tersisa satu kandidat.

bash
git bisect start HEAD HEAD~6 >/dev/null
git bisect bad
git bisect bad
text Keluaran
Previous HEAD position was 05abb1c Iterasi 5
Switched to branch 'main'
status: waiting for good commit(s), bad commit known
status: waiting for good commit(s), bad commit known

Setiap jawaban mempersempit rentang, dan keluaran sesi selalu menyebut sisa langkahnya. Alur manual ini juga menjadi jalan keluar ketika pengujian tidak dapat dikemas menjadi satu perintah, misalnya pengujian yang menuntut penilaian manusia pada antarmuka atau keluaran gambar, dan git bisect log mencatat jalannya sesi agar bisa dilanjutkan di lain waktu.

Kembali dari keadaan bisect#

Selama sesi bisect, HEAD berada pada keadaan khusus yang disebut refs/bisect, dan pekerjaan lain tidak boleh dilakukan di sana. Perintah git bisect reset mengembalikan branch ke keadaan sebelum sesi dimulai.

bash
git bisect reset
git log --oneline -1
text Keluaran
Already on 'main'
df109d0 Iterasi 7

Pemulihan ini wajib dilakukan sebelum melanjutkan pekerjaan biasa, dan Git mengingatkannya pada banyak perintah selama sesi berlangsung. Setelah reset, hasil pencarian berupa hash commit penyebab bug dapat langsung diperiksa dengan git show, dan pertanyaan mengapa perubahan itu dibuat dijawab dari pesan serta konteksnya.

Ringkasan#

  • git bisect mencari commit pertama yang buruk dengan pembagian dua, sehingga jumlah ujiannya tumbuh logaritmik terhadap panjang riwayat.
  • Sesi dimulai dengan git bisect start buruk baik, dan alur manualnya menyatakan tiap tengah dengan good atau bad.
  • git bisect run perintah mengotomatiskan seluruh langkah dengan kontrak keluaran nol berarti baik.
  • git bisect reset mengembalikan branch ke keadaan sebelum sesi, dan hasil pencariannya diperiksa dengan git show.

Referensi#