Tự động hóa kiểm tra code với Git Pre-commit Hook
Tìm hiểu cách hoạt động của Git pre-commit hook, cách chia sẻ hook qua repository và tự động format/lint code trước khi commit.
Hãy tưởng tượng bạn vừa viết xong một đoạn code tuyệt vời, hào hứng chạy git commit và push trực tiếp lên repository. Vài phút sau, hệ thống CI/CD báo lỗi đỏ rực chỉ vì… thừa một dấu phẩy hoặc quên chạy linter.
Tình huống này xảy ra rất thường xuyên. Làm sao để chúng ta chặn đứng các lỗi nhỏ này ngay tại máy cá nhân (Local) trước khi chúng kịp bước chân vào Git history? Câu trả lời chính là Git Pre-commit Hook.
Giới thiệu Git Pre-commit Hook#
Git Hooks là một tính năng tích hợp sẵn của Git, cho phép bạn kích hoạt các kịch bản (script) tự động tại các mốc thời điểm quan trọng trong vòng đời làm việc với Git (chẳng hạn như trước khi commit, trước khi push, hoặc sau khi checkout).
Trong đó, pre-commit hook chạy ngay khi bạn gõ lệnh git commit, trước cả khi Git tạo ra commit object. Nếu script trả về mã thoát (exit status) khác 0, quá trình commit sẽ bị hủy bỏ ngay lập tức.
graph LR
A[Lệnh git commit] --> B{Pre-commit Hook}
B -->|Mã thoát = 0| C[Tạo Commit thành công]
B -->|Mã thoát != 0| D[Hủy bỏ Commit & Báo lỗi]
Vấn đề & Giải pháp chia sẻ Hook trong Team#
Theo mặc định, các hook của Git nằm tại thư mục ẩn .git/hooks/. Tuy nhiên, thư mục .git lại không được đưa vào version control. Điều này dẫn đến hai hạn chế lớn:
- Khó chia sẻ trong team: Mỗi thành viên phải tự copy script vào thư mục
.git/hooks/của họ một cách thủ công. - Dễ bị lãng quên: Khi có thành viên mới tham gia dự án, họ thường bỏ qua bước thiết lập hook này.
Giải pháp với core.hooksPath#
Từ phiên bản Git 2.9, Git cung cấp cấu hình core.hooksPath cho phép chỉ định một thư mục bất kỳ làm nơi chứa hooks.
Chúng ta có thể lưu toàn bộ hook vào một thư mục được quản lý bởi Git (ví dụ .githooks/), sau đó thiết lập:
git config core.hooksPath .githooksbashKết hợp với file package.json (nếu dự án dùng Node.js/Bun), bạn có thể tự động hóa lệnh này thông qua script prepare:
{
"scripts": {
"prepare": "git config core.hooksPath .githooks"
}
}jsonMỗi khi thành viên trong team chạy npm install hoặc bun install, Git sẽ tự động sử dụng thư mục .githooks của dự án.
Thực hành: Tự động format Markdown với agent-md#
Dưới đây là ví dụ thực tế về script pre-commit hook: Tự động kiểm tra xem công cụ CLI agent-md có sẵn trên máy hay không, nếu có thì tự động format các file Markdown đang được staged và tự động git add lại.
#!/usr/bin/env bash
# 1. Kiểm tra xem CLI agent-md có tồn tại trên máy không
if command -v agent-md >/dev/null 2>&1; then
# 2. Lấy danh sách các file Markdown đang được staged (loại trừ file đã xóa)
STAGED_MD_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(md|mdx)$')
if [ -n "$STAGED_MD_FILES" ]; then
echo "[git-hook] Đang tự động format file Markdown với agent-md..."
for file in $STAGED_MD_FILES; do
if [ -f "$file" ]; then
agent-md "$file"
git add "$file"
fi
done
fi
fibashĐừng quên cấp quyền thực thi cho file script:
chmod +x .githooks/pre-commitbashCách bỏ qua Pre-commit Hook khi cần thiết#
Trong một số trường hợp khẩn cấp (như commit dở dang để đổi branch), bạn có thể tạm thời bỏ qua bước kiểm tra của pre-commit hook bằng cờ --no-verify (hoặc -n):
git commit -m "WIP: tạm thời bỏ qua check" --no-verifybash[!TIP] Hãy hạn chế dùng
--no-verifyđể đảm bảo chất lượng code luôn được đồng nhất trên toàn dự án.