Bản phát hành trước hoạt động, bản hiện tại lỗi, còn giữa hai mốc là hàng chục commit. Đọc mọi diff theo thứ tự có thể mất nhiều thời gian. Git bisect giúp thu hẹp lịch sử bằng những lần kiểm tra có chủ đích, nhưng chất lượng kết quả phụ thuộc vào cách xác định “lỗi”.
Bài viết tập trung vào một regression có thể tái hiện: cùng đầu vào nhưng kết quả bắt đầu sai sau một thay đổi. Các tên tag và file ví dụ cần thay bằng dữ liệu của dự án; không chạy thử trên thư mục đang có công việc chưa được lưu an toàn.
1. Viết tiêu chí lỗi trước khi mở lịch sử
“Trang có vẻ chậm” chưa đủ để phân loại commit. Một tiêu chí tốt hơn là “request với fixture này phải trả 200 và đúng trường total”, hoặc “hàm tính giá phải trả 10 cho bộ dữ liệu đã cố định”. Giữ phiên bản runtime, cấu hình và dữ liệu đầu vào trong biên bản điều tra.
Với lỗi hiệu năng, cần nhiều mẫu, cùng điều kiện cache và ngưỡng đủ cách biệt với nhiễu. Nếu cùng commit lúc pass lúc fail, hãy sửa phép thử trước; tự động hóa một tiêu chí không ổn định chỉ tạo ra kết quả nhanh nhưng khó tin cậy.
2. Xác minh trạng thái và hai mốc đầu cuối
git status --short
git rev-parse --verify HEAD
git rev-parse --verify 'stable-release^{commit}'
stable-release là tag minh họa của phiên bản được cho là còn tốt. git status giúp xem thay đổi trong index, working tree và các file chưa theo dõi; git rev-parse xác minh tên revision trước khi dùng.
Chạy cùng phép thử ở cả hai đầu: mốc cũ phải pass, mốc mới phải tái hiện đúng lỗi cần tìm. Ghi full commit ID để biên bản vẫn rõ khi branch hoặc tag thay đổi. Với repository thiếu lịch sử cũ, cần lấy đúng lịch sử trước khi kết luận không có commit phù hợp.
3. Thực hiện một phiên thủ công
Theo tài liệu git bisect, bắt đầu bằng một revision bad và một revision good; Git chọn các commit trung gian để kiểm tra. Sau mỗi phép thử, đánh dấu good hoặc bad rồi tiếp tục:
git bisect start
git bisect bad HEAD
git bisect good stable-release
# Chạy cùng phép thử tại revision Git vừa chọn.
# Chọn đúng một lệnh theo kết quả quan sát:
git bisect good
# hoặc: git bisect bad
Không chạy cả good lẫn bad liên tiếp như một đoạn script mẫu. Mỗi lệnh là một quyết định dựa trên kết quả tại revision đang checkout. Trong lúc Git chuyển revision, rebuild những phần cần thiết và dùng dependency lockfile tương ứng để tránh kiểm thử code cũ với môi trường của bản mới.
4. Một phép thử nhỏ để hiểu bisect run
Trong repository minh họa riêng, file value.txt chứa 10 ở hai commit đầu và 12 từ commit thứ ba. File check.php tồn tại từ đầu lịch sử:
<?php
$value = trim(file_get_contents(__DIR__ . '/value.txt'));
exit($value === '10' ? 0 : 1);
Sau khi có mốc baseline trỏ commit đầu và HEAD trỏ commit thứ năm, có thể chạy:
git bisect start HEAD baseline
git bisect run php check.php
Trong thử nghiệm local phục vụ bài viết, repository gồm năm commit như mô tả đã được chạy thật. Git tìm đúng commit thứ ba và phiên đã được kết thúc bằng bisect reset. Kết quả chỉ xác minh fixture đơn giản này; không chứng minh mọi dự án hay pipeline thực tế đã được kiểm tra.
Trong dự án thật, thay phép so sánh file bằng regression test nhỏ nhất tái hiện lỗi. Phép thử cần tồn tại hoặc được cung cấp ổn định cho mọi revision được kiểm tra. Nếu script chỉ có ở HEAD và biến mất sau checkout, hãy thiết kế harness bên ngoài repository thay vì để “không tìm thấy script” bị hiểu thành regression.
5. Đừng biến lỗi môi trường thành kết luận về code
Wrapper kiểm thử phải phân biệt đúng hành vi bị lỗi với dependency chưa cài, database không khởi động hoặc credential thiếu. Với bisect run, exit 0 biểu thị good, exit 1 biểu thị bad; 125 dùng cho revision không thể kiểm thử. Không chuyển mọi exception thành bad.
Ví dụ ứng dụng cần runtime cũ không còn trong máy: đây là trở ngại để chạy phép thử, chưa phải bằng chứng commit đó gây lỗi nghiệp vụ. Tương tự, một test gọi API bên ngoài rồi fail do timeout sẽ làm mốc good/bad phụ thuộc thời điểm mạng.
Nếu phải bỏ qua nhiều revision gần nơi chuyển trạng thái, kết quả có thể chỉ còn một tập ứng viên. Biên bản cần giữ sự chưa chắc chắn đó, không tự chọn commit có tên đáng nghi nhất.
6. Xác nhận ứng viên và khép lại phiên
git bisect log
git show --stat refs/bisect/bad
git bisect reset
Lưu log bằng cơ chế lưu văn bản phù hợp với shell đang dùng. Ghi lại commit được tìm thấy, tiêu chí pass/fail, môi trường và các revision bị bỏ qua. Sau reset, kiểm tra lại branch và working tree trước khi tiếp tục công việc.
“First bad” là ranh giới theo phép thử và khoảng lịch sử đã chọn, chưa tự giải thích nguyên nhân. Hãy đọc diff, tái hiện trên ứng viên và mốc tốt liên quan rồi viết regression test cho bản sửa. Một thay đổi dependency hoặc tương tác giữa nhiều commit cũng cần được điều tra.
7. Checklist để kết quả đáng tin cậy
- Hai đầu good/bad được xác nhận bằng cùng phép thử.
- Đầu vào, runtime và cấu hình đủ ổn định để lặp lại.
- Không sử dụng database production hoặc gửi email/webhook thật trong phép thử.
- Lỗi hạ tầng được tách khỏi lỗi hành vi; revision chưa test được không bị đoán là bad.
- Không giới hạn đường dẫn quá sớm nếu chưa biết lỗi nằm ở source, dependency hay cấu hình.
- Ứng viên được xác minh lại và có log điều tra.
- Phiên bisect đã reset; việc sửa lỗi được thực hiện trên branch làm việc phù hợp.
Giá trị lớn nhất của bisect nằm ở việc biến một nghi ngờ rộng thành một ranh giới có bằng chứng. Chuẩn bị phép thử tốt trước, để Git thu hẹp lịch sử, rồi dùng kết quả làm điểm bắt đầu cho phân tích nguyên nhân.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.