Ứng dụng hôm qua còn trả đúng kết quả, hôm nay một phép tính lại sai. Đọc lần lượt hàng chục commit là một lựa chọn, nhưng bạn có thể để Git chọn các mốc kiểm tra và thu hẹp phạm vi.
Bài này hướng dẫn git bisect với một lỗi tái hiện được. Các lệnh được đối chiếu tài liệu Git ngày 21/10/2026. Bạn nên thực hành trên repository thử hoặc một thư mục làm việc riêng trước khi dùng trong dự án đang có thay đổi dở.
1. Chuẩn bị một phép thử đủ rõ
Bạn cần hai commit: một commit đã biết có lỗi và một commit đã biết hành vi còn đúng. Quan trọng hơn, cần một thao tác có thể phân loại từng phiên bản một cách nhất quán.
Ví dụ: calculateTotal([100, 200]) phải cho kết quả 300. Đây là điều kiện hẹp hơn “màn hình bị chậm” hoặc “thỉnh thoảng không tải được”. Nếu lỗi chỉ xuất hiện ngẫu nhiên, hãy xử lý cách tái hiện trước; kết quả good/bad không ổn định sẽ dẫn cuộc tìm kiếm đi sai hướng.
Tài liệu git bisect mô tả cơ chế thu hẹp giữa mốc tốt và mốc xấu bằng tìm kiếm nhị phân. Git chọn commit, còn bạn hoặc script chịu trách nhiệm kết luận hành vi.
2. Làm việc trong thư mục điều tra riêng
Trước khi bắt đầu, xem trạng thái và các mốc có sẵn:
git status --short
git log --oneline -12
Nếu đang có thay đổi chưa lưu, đừng khởi động một phiên liên tục đổi checkout ngay trong thư mục đó. Một lựa chọn là tạo worktree detached từ HEAD theo tài liệu git worktree:
git worktree add --detach ../project-bisect HEAD
cd ../project-bisect
Tên thư mục chỉ là ví dụ; chọn một đường dẫn chưa tồn tại. Worktree riêng vẫn dùng chung lịch sử Git, nhưng có thư mục làm việc và index riêng. Bạn còn cần chuẩn bị dependency, biến môi trường và dữ liệu thử phù hợp trong thư mục mới.
3. Chạy bisect thủ công
Giả sử tag release-good là mốc đã kiểm tra không có lỗi. Hãy thay tag này bằng ref thực tế của repository:
git bisect start
git bisect bad HEAD
git bisect good release-good
Git checkout một commit trung gian. Quy trình khoanh vùng này cũng được minh họa trong Pro Git: Debugging with Git. Chạy phép thử của bạn, rồi dùng đúng một trong hai lệnh theo kết quả:
git bisect good
hoặc:
git bisect bad
Lặp lại cho đến khi Git báo commit đầu tiên trong phạm vi làm hành vi đổi sang bad. Đọc diff của commit được tìm thấy và chạy lại phép thử ở commit đó cùng commit cha trước khi kết luận nguyên nhân.
Nếu một commit không build được vì lý do khác, đừng gán nó là bad cho lỗi đang điều tra:
git bisect skip
Bỏ qua commit có thể khiến kết quả cuối cùng còn nhiều ứng viên. Đó là giới hạn cần báo rõ, không phải lý do chọn ngẫu nhiên một commit để kết thúc điều tra.
4. Tự động hóa khi có script ổn định
Nếu repository đã có một test hồi quy chạy một lần, bạn có thể để Git gọi test ở các mốc:
git bisect run ./scripts/check-regression.sh
Script cần trả mã thoát thể hiện đúng ý nghĩa: 0 là hành vi tốt; các mã từ 1 đến 127, trừ 125, được coi là xấu; 125 có nghĩa không kiểm tra được commit đó. Theo quy tắc bisect run, mã khác sẽ dừng quá trình.
Đừng dùng một script trả cùng mã lỗi cho cả “không cài được dependency” và “assertion sai”. Với lịch sử có thay đổi toolchain, bạn có thể cần tách bước chuẩn bị môi trường khỏi phép thử hành vi. Chỉ tự động hóa sau khi script đã phân loại đúng hai mốc đầu cuối.
5. Lưu kết quả và trở về trạng thái ban đầu
git bisect log
git bisect reset
Lưu log vào hồ sơ xử lý bug nếu cần tái hiện quá trình. Sau reset, kiểm tra lại git status và ref hiện tại. Nếu dùng worktree riêng, chỉ xóa nó sau khi đã giữ mọi ghi chú hoặc thay đổi cần thiết; bài này không yêu cầu xóa tự động.
Lỗi thường gặp
- Commit tốt thực ra chưa được kiểm tra: chạy lại phép thử ở cả hai mốc đầu cuối với cùng điều kiện.
- Test dựa vào dữ liệu mạng đang thay đổi: cố định dữ liệu đầu vào và phân biệt lỗi môi trường với lỗi phần mềm.
- Tìm được commit rồi chỉ đổ lỗi cho dòng sửa: xem cả thay đổi cấu hình, dependency và tương tác với code đã có.
Một phiên bisect tốt để lại ba thứ: điều kiện tái hiện rõ, commit hoặc tập ứng viên có bằng chứng, và một test có thể giữ lại để chống tái phát. Công cụ giúp chọn mốc nhanh hơn; chất lượng kết luận vẫn phụ thuộc phép thử của bạn.





