Git Pre-commit Hook — Tự Động Lint & Format Staged Files
Thiết lập Git pre-commit hook không phụ thuộc husky: tự động format Markdown, lint code và kiểm tra cú pháp Mermaid trên các file staged.
Khi làm việc theo nhóm hoặc viết blog/dự án, việc đảm bảo code và tài liệu Markdown chuẩn format trước khi commit lên Git là điều rất quan trọng. Thay vì phải nhớ chạy lệnh thủ công hoặc cài các thư viện cồng kềnh, bạn hoàn toàn có thể tận dụng Git Hooks native kết hợp core.hooksPath để tự động hóa 100%.
flowchart TD
Start(["Developer gõ git commit -m '...'"]) --> Hook[".githooks/pre-commit được kích hoạt"]
Hook --> Step1{"1. Kiểm tra Markdown staged<br/>(.md, .mdx)"}
Step1 -->|Có file| Formatter["Chạy agent-md format<br/>và git add file"]
Step1 -->|Không| Step2{"2. Kiểm tra Code staged<br/>(.ts, .tsx, .astro...)"}
Formatter --> Step2
Step2 -->|Có file| Linter["Chạy bun lint (ESLint)<br/>và git add file"]
Step2 -->|Không| Step3{"3. Kiểm tra Docs/Diagrams staged"}
Linter --> Step3
Step3 -->|Có file| MermaidLinter["Chạy bun lint:mermaid (maid)"]
Step3 -->|Không| Done(["Tạo Commit Thành Công ✅"])
MermaidLinter -->|Lỗi cú pháp| Abort(["Commit Bị Chặn ❌<br/>Yêu cầu sửa lỗi trước"])
MermaidLinter -->|Hợp lệ| Done
Tại Sao Dùng Native Git Hooks Thay Vì Husky?#
flowchart LR
subgraph HuskyApproach["Cách tiếp cận với Husky"]
H1["Cài đặt thêm npm package husky"]
H2["Tăng node_modules size"]
H3["Phụ thuộc runtime bên ngoài"]
end
subgraph NativeApproach["Git Native Hook (core.hooksPath)"]
N1["Chỉ cần 1 bash script trong .githooks/"]
N2["Zero dependencies"]
N3["Version control theo Git repository"]
end
| Tiêu chí | Husky / Thư viện thứ 3 | Git Native Hook (core.hooksPath) |
|---|---|---|
| Dependency | Cần cài package | 0 dependency |
| Tốc độ | Khởi động qua wrapper Node.js | Shell script thực thi tức thì (<10ms) |
| Chia sẻ qua Git | Có | Có (qua thư mục .githooks/) |
Cấu Trúc Script Pre-commit Hoàn Chỉnh#
File cấu hình đặt tại .githooks/pre-commit:
#!/usr/bin/env bash
set -e
# 1. Format staged markdown files with agent-md if available
if command -v agent-md >/dev/null 2>&1; then
STAGED_MD_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(md|mdx)$' || true)
if [ -n "$STAGED_MD_FILES" ]; then
echo "[git-hook] Running agent-md format on staged markdown files..."
for file in $STAGED_MD_FILES; do
if [ -f "$file" ]; then
agent-md "$file"
git add "$file"
fi
done
fi
fi
# 2. Lint changed code files with bun lint
STAGED_CODE_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(js|jsx|ts|tsx|astro)$' || true)
if [ -n "$STAGED_CODE_FILES" ]; then
echo "[git-hook] Running bun lint on staged code files..."
bun lint
for file in $STAGED_CODE_FILES; do
if [ -f "$file" ]; then
git add "$file"
fi
done
fi
# 3. Lint mermaid diagrams with bun lint:mermaid
STAGED_DOC_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(md|mdx|html|astro)$' || true)
if [ -n "$STAGED_DOC_FILES" ]; then
echo "[git-hook] Running bun lint:mermaid on diagrams..."
bun lint:mermaid
fibashPhân Tích Logic Chi Tiết#
1. Lọc File Đang Staged Với git diff --cached#
flowchart LR
GitIndex["Git Index (Staged Area)"] --> Filter["git diff --cached --name-only --diff-filter=d"]
Filter --> Regex["grep -E '\\.(ext)$'"]
Regex --> Files["Danh sách file cần xử lý"]
--cached: Chỉ kiểm tra các file đã đượcgit add.--diff-filter=d: Loại trừ các file đã bị xóa (deleted) để tránh lỗi khi script cố đọc file không tồn tại.set -e: Dừng tiến trình ngay lập tức và chặn commit nếu bất kỳ lệnh lint nào trả về lỗi (exit code khác 0).
2. Tự Động Re-Stage Sau Khi Format#
Khi agent-md hoặc bun lint sửa đổi nội dung file để chuẩn hóa, script thực hiện git add "$file" để cập nhật các thay đổi đó trực tiếp vào commit hiện tại mà không cần developer thao tác lại.
Thiết Lập Tự Động Kích Hoạt Trong Dự Án#
Thêm script prepare vào package.json:
{
"scripts": {
"prepare": "git config core.hooksPath .githooks",
"lint": "eslint --fix 'src/**/*.{js,ts,jsx,tsx,astro}'",
"lint:mermaid": "maid docs/ src/"
}
}jsonCấp quyền thực thi cho file hook:
chmod +x .githooks/pre-commit
bun run preparebashKhi bất kỳ ai clone repository và chạy bun install, bun sẽ tự động kích hoạt script prepare để trỏ Git hooks về thư mục .githooks.
Kết Luận#
Chỉ với một file shell script nhỏ gọn:
- Toàn bộ Markdown được định dạng tự động.
- Mã nguồn TypeScript/Astro luôn tuân thủ chuẩn ESLint.
- Sơ đồ Mermaid được kiểm tra toàn vẹn, loại bỏ triệt để lỗi cú pháp trước khi push lên remote.