Panduan

git bisect: cara menemukan commit yang merusak kode

Diperbarui: · Skillaria.Top

git bisect menemukan commit tempat sebuah error muncul dengan pencarian biner di riwayat. Jalankan git bisect start, tandai commit yang rusak dengan git bisect bad dan commit yang masih benar dengan git bisect good <hash>, lalu periksa commit yang diusulkan sampai Git menunjuk pelakunya; di akhir jalankan git bisect reset.

git bisect mencari commit yang memasukkan bug dengan metode pencarian biner. Anda menentukan satu commit tempat bug masih ada dan satu commit tempat bug belum ada. Git lalu memindahkan Anda ke tengah rentang dan bertanya: «di sini berfungsi atau rusak?». Setiap jawaban memangkas separuh kandidat, sehingga dari 1000 commit pelakunya ketemu sekitar 10 kali pengecekan.

Ini sangat berguna ketika bug tidak jelas penyebabnya: tes gagal, performa turun, tampilan berantakan, tetapi diff tidak memberi petunjuk. Alih-alih membaca ratusan perubahan, Anda cukup mengajukan pertanyaan sederhana yang sama berulang kali.

Cara kerja pencarian biner di riwayat

Misalnya versi yang masih benar adalah v2.3 dan kondisi saat ini adalah main, dengan 200 commit di antaranya. Git mengambil commit di tengah dan mengeceknya. Jika di sana sudah rusak, error muncul di paruh pertama; jika tidak, error muncul di paruh kedua. Jumlah kandidat berkurang setengah pada setiap langkah: 200, 100, 50, 25, 13, 7, 4, 2, 1. Delapan pengecekan, bukan dua ratus.

Syarat utamanya: kondisi «rusak» harus bersifat monoton. Jika bug muncul, hilang, lalu muncul lagi, bisect memang akan menemukan salah satu titik peralihan, tetapi belum tentu titik yang Anda cari.

git bisect langkah demi langkah: mode manual

1. Tentukan commit yang baik dan yang rusak

Commit yang rusak biasanya HEAD saat ini. Commit yang baik adalah commit yang pasti berfungsi: tag rilis sebelumnya, atau commit dari seminggu lalu. Untuk mencarinya, gunakan git log --oneline, git tag, atau git log --since="2 weeks ago".

2. Mulai sesi

git bisect start
git bisect bad                 # commit saat ini rusak
git bisect good v2.3           # di rilis v2.3 semuanya berfungsi
Bisecting: 99 revisions left to test after this (roughly 7 steps)
[4f5e6d7c...] Perbarui dependensi frontend

Hal yang sama bisa ditulis dalam satu baris: git bisect start HEAD v2.3, yaitu commit yang rusak lebih dulu, lalu yang baik. Git langsung memindahkan direktori kerja ke commit di tengah (dalam kondisi detached HEAD).

3. Periksa dan tandai

Build proyeknya, jalankan tes, atau reproduksi bug secara manual. Lalu laporkan hasilnya:

git bisect good     # di sini berfungsi
Bisecting: 49 revisions left to test after this (roughly 6 steps)

git bisect bad      # di sini rusak
Bisecting: 24 revisions left to test after this (roughly 5 steps)

4. Dapatkan hasilnya

Saat tinggal satu kandidat, Git menampilkannya:

a1b2c3d4e5f6... is the first bad commit
commit a1b2c3d4e5f6...
Author: Ivan Petrov <ivan@example.com>
Date:   Tue Sep 29 11:40:12 2026 +0300

    Cache hasil perhitungan keranjang

 src/cart.js | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

5. Akhiri sesi

git bisect reset

Perintah ini mengembalikan Anda ke cabang tempat Anda memulai. Jangan lupakan langkah ini: selama sesi belum ditutup, Anda masih berada di detached HEAD dan commit baru mudah hilang. Dengan git bisect reset HEAD Anda tetap berada di commit yang ditemukan, sedangkan git bisect reset <commit> membawa Anda ke commit yang Anda tentukan.

Pencarian otomatis: git bisect run

Jika pengecekan bisa dinyatakan dalam satu perintah, serahkan seluruh pekerjaan kepada Git. git bisect run menjalankan skrip di setiap langkah dan menandai commit berdasarkan kode keluarnya:

Kode keluarArti
0good — commit baik
1–127, kecuali 125bad — commit rusak
125skip — commit tidak bisa diperiksa, lewati
di atas 127 (atau <0)hentikan bisect (misalnya skrip berhenti karena sinyal)

Contoh penggunaan:

git bisect start HEAD v2.3
git bisect run npm test
git bisect run pytest tests/test_cart.py -x
git bisect run make check

Untuk pengecekan yang rumit, buat skrip kecil. Penting untuk memisahkan «tidak bisa di-build» dari «bug muncul». Jika tidak, bisect akan menganggap build yang rusak sebagai bug yang dicari:

#!/bin/sh
# check.sh
npm ci --silent || exit 125      # dependensi gagal dipasang — lewati
npm run build   || exit 125      # tidak bisa di-build — lewati
node scripts/check-cart-total.js # 0 — oke, 1 — bug
chmod +x check.sh
git bisect run ./check.sh

Simpan skrip di luar file yang dilacak atau di folder yang ada di setiap commit yang diperiksa. Bisect memindahkan direktori kerja, dan file yang baru ditambahkan akan hilang pada commit lama. Cara paling aman adalah menaruhnya di /tmp atau di folder lain di luar repositori.

Tes yang belum ada di commit lama

Situasi yang sering terjadi: Anda sudah menulis tes yang mereproduksi bug, tetapi file tes itu tidak ada di commit lama. Solusinya adalah menyalin tes tersebut ke luar repositori:

cp tests/test_regression.py /tmp/
git bisect run pytest /tmp/test_regression.py

git bisect skip: saat commit tidak bisa diperiksa

Terkadang commit di tengah tidak bisa di-build atau gagal karena alasan lain. Anda tidak boleh menandainya good atau bad, karena hasilnya akan keliru. Lewati saja:

git bisect skip
git bisect skip v2.4..v2.4.3   # lewati satu rentang

Git akan memilih commit tetangganya. Jika commit yang dilewati berada tepat di batas, di akhir Anda akan melihat daftar «kemungkinan pelaku», bukan satu saja. Dalam kasus itu, periksa diff-nya satu per satu.

Istilah sendiri sebagai pengganti good dan bad

Bisect tidak hanya dipakai untuk mencari bug. Misalnya, Anda ingin tahu commit mana yang membuat halaman termuat lebih cepat. Menyebut commit cepat sebagai «rusak» membingungkan, jadi tersedia istilah alternatif:

git bisect start --term-old=slow --term-new=fast
git bisect fast HEAD
git bisect slow v2.3

Sinonim bawaannya adalah old dan new: git bisect new, git bisect old. Aturannya hanya satu: keadaan «lama» harus berada pada commit yang lebih awal.

Log sesi: log, replay, visualize

  • git bisect log — menampilkan semua penandaan Anda. Simpan ke file jika sesinya panjang.
  • git bisect replay file — mengulang sesi dari log. Salah pada langkah keenam? Simpan log, hapus baris yang keliru, jalankan git bisect reset, lalu replay.
  • git bisect visualize (atau git bisect view) — menampilkan kandidat yang tersisa; dengan --oneline hasilnya ditampilkan lewat git log.
git bisect log > /tmp/bisect.log
# perbaiki log
git bisect reset
git bisect replay /tmp/bisect.log

Bisect dan merge commit

Dalam riwayat dengan banyak merge, bisect bisa membawa Anda masuk ke dalam cabang yang sudah digabungkan, yaitu ke commit-commit yang dibuat sebelum cabang itu disinkronkan dengan main dan karena itu berada di basis yang berbeda. Jika Anda ingin lebih dulu mengetahui merge mana yang membawa bug, gunakan:

git bisect start --first-parent

Dengan opsi ini Git hanya menelusuri parent pertama dari merge commit, yaitu riwayat cabang utama. Setelah menemukan merge yang bersalah, Anda bisa menjalankan bisect kedua di dalam cabang tersebut.

Kesalahan yang sering terjadi

  • Keliru menandai good dan bad. Hasilnya tidak berarti apa-apa. Pulihkan sesi lewat git bisect log dan replay, tanpa memulai dari awal.
  • Direktori kerja kotor. Perubahan yang belum di-commit menghalangi perpindahan antar-commit dan memengaruhi hasil pengecekan. Sebelum mulai, lakukan commit atau git stash.
  • Artefak build belum dibersihkan. Cache lama atau node_modules dari commit lain memberi hasil yang keliru. Buat build yang bersih di dalam skrip.
  • Tes yang tidak stabil (flaky). Jika tes kadang gagal dengan sendirinya, bisect akan menandai commit yang acak. Jalankan pengecekan beberapa kali atau perbaiki tesnya dulu.
  • Lupa reset. Anda masih berada di detached HEAD lalu mulai bekerja. Commit yang hilang bisa dicari lewat reflog.

Contoh: mencari regresi dari awal sampai akhir

Pengguna melaporkan bahwa total keranjang dihitung salah ketika ada diskon. Di rilis v2.3 hasilnya benar, di main tidak. Kita tulis pengecekan minimal lalu jalankan pencarian:

cat > /tmp/check.sh <<'SH'
#!/bin/sh
npm ci --silent || exit 125
node -e "const c=require('./src/cart'); process.exit(c.total([{price:100}], 0.1) === 90 ? 0 : 1)"
SH
chmod +x /tmp/check.sh

git stash                       # simpan perubahan yang belum di-commit
git bisect start HEAD v2.3
git bisect run /tmp/check.sh
...
a1b2c3d4e5f6... is the first bad commit
git bisect log > /tmp/cart-bisect.log
git bisect reset
git stash pop

Pencarian di antara seratus commit berjalan tanpa campur tangan Anda, sementara Anda bisa mengerjakan hal lain. Log yang disimpan berguna jika Anda perlu menunjukkan kepada rekan tim bagaimana pelakunya ditemukan.

Apa yang dilakukan setelah commit ditemukan

Setelah pelakunya ketemu, lihat seluruh commit itu: git show a1b2c3d. Commit kecil dengan pesan yang jelas biasanya langsung menunjukkan penyebabnya. Inilah salah satu alasan tim menghargai commit atomik: bisect hampir tidak berguna pada riwayat yang penuh commit «fix stuff» berukuran raksasa. Setelah itu ada dua pilihan: memperbaiki bug dengan commit baru, atau jika perubahannya memang keliru dan sudah dipublikasikan, membatalkannya dengan git revert a1b2c3d.

Ringkasan

git bisect mengubah pencarian regresi dari membaca ratusan diff menjadi beberapa jawaban «berfungsi / tidak berfungsi», dan dengan git bisect run menjadi satu perintah saja. Yang dibutuhkan hanya dua patokan, yaitu commit yang baik dan commit yang rusak, serta pengecekan yang bisa diulang. Membaca riwayat, bernavigasi di antara commit, dan mencari bug di dalamnya dibahas dengan praktik dalam kursus Git.

Pertanyaan umum

Berapa langkah yang dibutuhkan git bisect?

Kira-kira logaritma dua dari jumlah commit dalam rentang: sekitar 7 langkah untuk 100 commit dan sekitar 10 untuk 1000. Git sendiri menampilkan perkiraan jumlah langkahnya dengan tulisan roughly N steps.

Bisakah bisect dijalankan jika commit yang baik tidak diketahui?

Harus ada setidaknya satu. Pilih commit lama yang pasti benar atau tag rilis, lalu periksa sendiri. Langkah tambahan karena rentang yang lebar hampir tidak memakan waktu.

Apakah git bisect mengubah riwayat repositori?

Tidak. Ia hanya memindahkan direktori kerja di antara commit dan menyimpan penandaan di referensi sementara refs/bisect, yang dihapus saat git bisect reset.

Bisakah menandai beberapa commit sebagai good sekaligus?

Bisa. Perintah git bisect good menerima beberapa commit sekaligus, yang mempersempit rentang, terutama pada riwayat bercabang.

Apakah bisect hanya untuk mencari bug?

Tidak. Bisect bisa dipakai untuk menemukan titik perubahan apa pun: kapan sebuah file muncul, kapan build menjadi lebih cepat, atau kapan perilaku berubah. Untuk keperluan ini istilah old/new atau istilah sendiri lewat --term-old dan --term-new sangat membantu.

Pelajari topik ini lewat video

Topik ini dibahas mendalam dengan praktik di kursus “Git dari Nol hingga Pengembang Percaya Diri”.

Ke kursus