Nỗi ám ảnh mang tên “Regression Bug”
Sáng thứ Hai đến công ty, khách hàng báo lỗi gấp trên production. Bạn bàng hoàng nhận ra một tính năng quan trọng vừa “bay màu”, dù tuần trước vẫn chạy tốt. Ác mộng thực sự bắt đầu khi nhìn vào lịch sử Git: team đã merge hơn 200 commit trong 2 tuần qua.
Rà soát thủ công từng commit để tìm điểm gãy là một cực hình. Trước đây, mình thường dùng git bisect theo cách truyền thống. Mình chọn một commit cũ chắc chắn chạy tốt (good), chọn commit hiện tại bị lỗi (bad), rồi để Git đưa về vị trí giữa. Tại mỗi điểm dừng, mình phải build code, chạy thử bằng tay, rồi gõ git bisect good hoặc bad. Quy trình này lặp lại khoảng 7-10 lần cho đến khi tìm ra thủ phạm.
Dù nhanh hơn việc check từng commit, cách này vẫn tốn thời gian ngồi chờ build. Mọi thứ thay đổi khi mình biết tới lệnh git bisect run. Thay vì ngồi canh để gõ lệnh, mình chỉ cần viết một script kiểm tra nhỏ rồi đi pha cafe. Khi quay lại, Git đã chỉ đích danh commit gây lỗi. Kỹ thuật này từng cứu nguy cho mình trong một đợt release căng thẳng, giúp phát hiện lỗi logic ẩn sâu trong 5.000 dòng code mới.
Git bisect run – Để máy tính tự săn bug
Git sử dụng thuật toán tìm kiếm nhị phân (binary search) để tối ưu hóa việc truy vết. Với một danh sách 1.000 commit, bạn chỉ cần tối đa 10 lần kiểm tra để xác định đúng vị trí lỗi.
Điểm khác biệt của git bisect run là khả năng thực thi một script tự động. Git sẽ tự động checkout sang commit tiếp theo và chạy script đó. Dựa vào kết quả trả về, Git tự quyết định commit đó là “tốt” hay “xấu” và tiếp tục nhảy bước cho đến khi có kết quả cuối cùng.
Nguyên lý vận hành: Sức mạnh của Exit Code
Để git bisect run hoạt động chính xác, script của bạn phải trả về mã thoát (exit codes) đúng quy ước:
- Exit code 0: Commit hoạt động tốt (Good).
- Exit code từ 1 đến 127 (trừ 125): Commit bị lỗi (Bad).
- Exit code 125: Không thể kiểm tra commit này (ví dụ lỗi build không liên quan), Git sẽ bỏ qua và chọn commit lân cận.
Chỉ cần viết một script (Bash, Python, Node.js…) trả về 0 khi thành công và 1 khi thất bại, bạn đã tự động hóa được toàn bộ quá trình tìm lỗi.
Thực hành: Tự động hóa quy trình truy vết
Giả sử bạn có một dự án Node.js bị sai logic tính toán. Bạn biết bản tag v1.0 vẫn đúng, nhưng HEAD hiện tại lại cho kết quả sai.
Bước 1: Viết script kiểm thử (test.sh)
Tạo file test.sh để thực hiện các bước kiểm tra tự động. Bạn nên đặt file này ở thư mục cha (ngoài repo) để tránh bị ảnh hưởng khi Git checkout.
#!/bin/bash
# 1. Cập nhật dependency nếu các commit có thay đổi package.json
npm install
# 2. Chạy script kiểm tra logic cụ thể
# File test_logic.js sẽ throw error nếu kết quả không như mong đợi
node test_logic.js
# 3. Trả về trạng thái của lệnh vừa chạy
exit $?
Nếu bạn chỉ cần tìm xem một file có chứa từ khóa gây lỗi hay không, hãy dùng grep cho nhanh:
#!/bin/bash
# Nếu tìm thấy chuỗi "buggy_function", coi như commit đó lỗi
! grep -q "buggy_function" src/utils.js
Bước 2: Kích hoạt chế độ tự động
Mở terminal và ra lệnh cho Git bắt đầu làm việc:
git bisect start
# Đánh dấu điểm đầu và điểm cuối
git bisect bad
git bisect good v1.0
# Kích hoạt chế độ tự động với script
git bisect run sh ../test.sh
Git sẽ bắt đầu nhảy qua các commit và chạy script liên tục. Sau vài phút, màn hình sẽ hiển thị thông báo quan trọng nhất:
f7a3b2c... is the first bad commit
Kinh nghiệm thực tế để không bị “hố”
Sau nhiều lần áp dụng cho team 8 người, mình rút ra 4 lưu ý quan trọng để bisect run đạt hiệu quả cao nhất:
- Môi trường sạch: Script nên bao gồm bước dọn dẹp hoặc cài đặt lại môi trường (như
npm install). Nếu không, các dependency cũ có thể làm sai lệch kết quả test giữa các commit. - Ưu tiên tốc độ: Git sẽ chạy script nhiều lần. Thay vì chạy toàn bộ test suite mất 20 phút, hãy viết một test case nhỏ chỉ tập trung vào đúng lỗi đang tìm.
- Đường dẫn file: Luôn sử dụng đường dẫn tuyệt đối hoặc đặt script bên ngoài thư mục dự án. Điều này đảm bảo script không bị mất hoặc thay đổi nội dung khi Git quay ngược thời gian.
- Quyền thực thi: Luôn nhớ chạy
chmod +x test.shtrước khi bắt đầu trên hệ điều hành Linux hoặc macOS.
Lời kết
Việc tìm ra commit lỗi thường chiếm đến 50% thời gian xử lý sự cố. Với git bisect run, bạn đã đẩy phần việc nhàm chán nhất cho máy tính xử lý.
Trong một dự án trước đây, mình từng gặp lỗi vỡ giao diện CSS rất khó tìm. Mình đã viết script dùng Puppeteer để chụp ảnh màn hình và so sánh pixel tự động. Kết quả là tìm ra đúng commit sửa nhầm biến global CSS chỉ sau 5 phút chạy máy. Lần tới khi gặp lỗi khó, đừng vội mò mẫm code ngay, hãy thử để Git làm thám tử thay bạn.

