Git Bisect

Vào một buổi sáng đẹp trời ngày nọ, mình đến công ty vào lúc 7h30, nhai tạm cái bánh mì que mua ở trên đường đi làm, thảnh thơi pha thêm cốc cafe cho tỉnh hẳn ngủ. Tranh thủ mở Slack ra check chợt thấy khách hàng kêu gào từ hơn 1 tiếng trước, nguyên nhân là end user phát hiện ra 1 lỗi liên quan đến phần điền thông tin vận chuyển trong màn hình thanh toán. Vứt cái bánh mì gặm dở sang 1 bên, mình vâng vâng dạ dạ với KH rồi bắt đầu mở server lên tái hiện lại thì thấy có bug đó thật.

Trong bụng lúc đó nghĩ: "Lạ vãi, chức năng này mình làm cũng gần nửa năm rồi, lúc đó cả KH cũng test xong rồi mới delivery mà giờ lại đẻ ra bug :-s". Vậy chỉ có thể là có ông nào đó sửa mất hàm dùng chung rồi không test kĩ lại rồi. Dự án này mình làm với khoảng hơn 10 người nữa nên chắc điều đó là điều không thể tránh khỏi. Tóm lại là phải tìm ra và fix càng nhanh càng tốt sau đó release hotfix để tránh ảnh hưởng đến end user.

Mở gitk ra xem từ lần release chức năng của mình có ai sửa file gì liên quan không thì thấy gần 200 commit liên quan 😳 WTF. Giờ mà ngồi dò từng commit kiểu checkout rồi tái hiện lại cũng hết cả hơi 🥶

Thử checkout vài commit gần đây nhất để check thì thấy bug đã có rồi, có nghĩa là cần phải check thêm những commit cũ hơn nữa. Nghĩ tới việc ngồi checkout lần lượt 200 commit để test làm mình toát mồ hôi hột, thôi thì nghĩ thử xem có cách nào lười được không? Cái khó ló cái khôn, hay là thử áp dụng tìm kiếm nhị phân xem, cứ chia đôi chỗ commit từ commit không lỗi của mình đến commit mới nhất. Sau đó kiểm tra xem tại commit đó có lỗi không, nếu không có lỗi thì mình tìm ở nửa còn lại, nếu có lỗi thì tiếp tục chia đôi và tìm tiếp.

Cách này có vẻ khả thi và đỡ tốn công hơn cách trước rồi, nhưng có 1 cái bất tiện đó là mình phải tự đếm và chia bằng tay, ngồi thử làm 1 step thì thấy ngồi dò dò rồi đếm từng commit vẫn mệt quá 😅Thử Google xem có cách nào đếm và chia commit theo kiểu binary search với keyword "git binary search" thì thấy kết quả đầu tiên nói về git bisect. Click đọc thử thấy mừng quá, đây đúng là thứ mình cần rồi.

git-bisect - Use binary search to find the commit that introduced a bug

git-bisect là một tool có sẵn trong package Git, nó sử dụng thuật toán tìm kiếm nhị phân để tìm ra commit đầu tiên gây ra bug.

Cách sử dụng cũng khá đơn giản như sau:

  • Chạy tool git-bisect.
  • Báo với git-bisect biết commit nào không bug (good), commit nào có bug (bad).
  • git-bisect sẽ chạy từng bước và checkout 1 commit, mình chỉ việc check lại commit đó có bug hay không bằng cách nói với nó good hoặc bad.
  • Sau khi chạy xong các bước, git-bisect sẽ chỉ ra commit đầu tiên mà gây ra lỗi.
# Bắt đầu git-bisect
git bisect start

# Báo cho git-bisect biết commit không có bug (commit hash: abcdef)
git bisect good abcdef

# Báo cho git-bisect biết commit có bug (commit hash: fedcab)
git bisect bad fedcab

# Sau khi git-bisect chạy qua mỗi step, check lại bug và report
# Report bad nếu commit hiện tại có bug
# Report good nếu commit hiện tại không bug
git bisect bad
git bisect good

# Đến step cuối cùng, git-bisect sẽ show ra commit đầu tiên mà gây ra bug.

Vì việc show commits vi phạm an toàn thông tin cho nên mình sẽ không show ra, nhưng hy vọng video dưới đây sẽ giải thích được cũng như hướng dẫn cách sử dụng git bisect cho mọi người.

Ngoài cách sử dụng git bisect thủ công như trên, mình có thể chạy git bisect tự động thông qua git bisect run <command>. Lúc đó, ở mỗi step, git bisect sẽ tự động thực thi command mà mình đã set, nếu command đó có exit code là 0 đồng nghĩa với good, khác 0 đồng nghĩa với bad.

Giả sử mình đang có 1 API bị lỗi, server trả về response không đúng, mình sẽ viết một đoạn script nhỏ trong đó thực hiện tạo 1 request đến API đó, nếu trong response trả về đúng như ý muốn của mình thì sẽ exit 0, còn không thì exit 1. Và chỉ cần như thế, git bisect sẽ làm nốt phần việc còn lại cho mình, mình có thể dành thời gian làm việc khác thay vì mất công ngồi reproduce bug bằng tay.

git bisect start

git bisect good abcdef
git bisect bad defabc

git bisect run python3 request.py

Vậy là sau một hồi mày mò tìm hiểu, cũng nhờ bản tính lười có sẵn trong người mà mình đã tiết kiệm được khá nhiều thời gian ngồi điều tra bug, nếu mà cứ làm bằng tay kiểu trâu bò chắc cũng mất cả ngày trời 😳Sau khi fix được bug, KH cũng rất vui mừng và dành hết lời khen ngợi tinh thần làm việc cũng như chất lượng công việc của mình với cấp trên của mình. Cũng chính vì đó mà cuối năm đó mình đã được công ty trao tặng 1 cái cúp cực kì ý nghĩa với mình 🤪

Hy vọng bài viết này sẽ có ích với mọi người. Cái đoạn trên mình viết cho vui chứ không phải thật đâu 😬😬😬Hẹn mọi người ở bài viết khác nhé.