Domain 5 · 9 phút đọc

Bisect: truy vết commit gây bug bằng binary search

Bisect: Tracking Down the Buggy Commit with Binary Search

Bug mới xuất hiện nhưng bạn không biết commit nào gây ra, mà nhánh có hàng trăm commit? Dò từng cái thì quá lâu. Bisect dùng tìm kiếm nhị phân binary search để khoanh vùng commit lỗi chỉ trong vài bước.

Ý tưởng: binary search trên lịch sử

Bạn biết một commit cũ chạy tốt (good) và commit hiện tại bị lỗi (bad). Bisect liên tục checkout commit ở giữa khoảng đó, hỏi bạn good hay bad, rồi loại bỏ một nửa. Với 1000 commit, bạn chỉ cần kiểm tra khoảng 10 lần (log2 của 1000).

Quy trình thủ công

# Bắt đầu phiên bisect
git bisect start

# Đánh dấu commit hiện tại là lỗi
git bisect bad

# Đánh dấu một commit cũ đã biết là tốt
git bisect good v1.2.0

Git tự checkout commit ở giữa. Bạn build/test rồi báo kết quả:

# Nếu commit này còn tốt:
git bisect good
# Nếu commit này đã lỗi:
git bisect bad

Lặp lại cho tới khi Git in ra: <hash> is the first bad commit. Khi xong:

# Trả HEAD về trạng thái ban đầu
git bisect reset

Tự động hóa với bisect run

Nếu bạn có một script/test trả về exit code 0 khi tốt, khác 0 khi lỗi, hãy để Git tự chạy toàn bộ:

git bisect start HEAD v1.2.0   # bad good gộp một dòng
git bisect run ./test-bug.sh

Bisect run sẽ tự checkout, chạy script và phân loại good/bad ở mỗi bước cho tới khi tìm ra thủ phạm — không cần bạn ngồi canh.

# Ví dụ test-bug.sh
#!/bin/bash
npm run build || exit 125   # 125 = bỏ qua commit không build được
npm test -- --grep "login"  # exit code quyết định good/bad

Mã 125 để bỏ qua commit

Trong script bisect, trả về exit code 125 cho những commit không thể test được (build hỏng, thiếu dependency). Git sẽ bỏ qua chúng thay vì tính là good/bad, giúp kết quả chính xác.

Đừng quên bisect reset

Trong lúc bisect, bạn đang ở trạng thái detached HEAD trên các commit cũ. Luôn chạy git bisect reset khi xong để quay về nhánh ban đầu, tránh commit nhầm vào trạng thái rời.

Trọng tâm thi

bisect = tìm kiếm nhị phân để tìm first bad commit. Cần một mốc good và một mốc bad; mỗi bước loại nửa số commit. git bisect run <script> tự động hóa bằng exit code (0 = good, khác 0 = bad, 125 = bỏ qua).

Tóm tắt

  • git bisect dùng binary search để tìm commit đầu tiên gây bug giữa một mốc good và một mốc bad.
  • Quy trình: bisect startbisect badbisect good <ref> → trả lời good/bad mỗi bước → bisect reset.
  • Mỗi bước loại bỏ một nửa lịch sử, nên cực nhanh với repo lớn.
  • git bisect run <script> tự động hóa bằng exit code: 0 = good, khác 0 = bad, 125 = bỏ qua commit.
  • Luôn git bisect reset để rời detached HEAD và về nhánh ban đầu.