blog.dopana

Back

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ứ 3Git Native Hook (core.hooksPath)
DependencyCần cài package0 dependency
Tốc độKhởi động qua wrapper Node.jsShell script thực thi tức thì (<10ms)
Chia sẻ qua GitCó (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:

Phâ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 đã được git 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/"
  }
}
json

Cấp quyền thực thi cho file hook:

chmod +x .githooks/pre-commit
bun run prepare
bash

Khi 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.

Tài liệu tham khảo#