Git Hooks: Tự động hóa kiểm tra code trước khi commit

Git Hooks: Tự động hóa kiểm tra code trước khi commit

VS Code IDE with pre-commit hooks configuration on split screen
VS Code IDE with pre-commit hooks configuration on split screen

Git hooks là script tự chạy ở các sự kiện cụ thể trong vòng đời Git. pre-commitpre-push hooks giúp tự động kiểm tra code chất lượng trước khi commit hoặc push — loại bỏ sai sót human tại điểm nghiêm trọng nhất.

Git hooks hoạt động thế nào?

Mỗi hook là script đặt trong .git/hooks/. Git gọi hook ở sự kiện tương ứng. Hook trả về exit code 0 = cho phép, khác 0 = chặn:

  • pre-commit: Chạy trước khi tạo commit — kiểm tra syntax, lint, test nhanh
  • prepare-commit-msg: Sửa message commit tự động trước khi editor mở
  • pre-push: Chạy trước khi push — kiểm tra branch, test toàn bộ
  • post-commit: Chạy sau commit thành công — thông báo, sync
  • post-merge: Chạy sau khi merge/clone — cài đặt dependencies
Matrix-style code rain representing Git automation pipeline
Matrix-style code rain representing Git automation pipeline

pre-commit hook thực hành

Hook phổ biết nhất là pre-commit. Ví dụ chạy lint và kiểm tra syntax trước khi cho phép commit:

#!/bin/bash
# .git/hooks/pre-commit

echo "🔍 Running pre-commit checks..."

# Lint staged files
STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep '.py$')

for file in $STAGED; do
    if [ -f "$file" ]; then
        echo "Linting $file..."
        ruff check "$file" || exit 1
    fi
done

# Run fast tests
echo "Running tests..."
pytest tests/ -q --tb=short || exit 1

echo "✅ All checks passed!"

Hook này kiểm tra cú pháp Ruff (thay vì flake8 — nhanh hơn 5×) và chạy test. Nếu bất kỳ bước nào thất bại, commit bị chặn.

Quản lý hooks với pre-commit framework

Viết hook thủ công trong .git/hooks/ KHÔNG version-control được. Framework pre-commit giải quyết vấn đề này:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-merge-conflict
      - id: check-xml
      - id: check-yaml
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.7
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format
  - repo: https://github.com/psf/black
    rev: 24.3.0
    hooks:
      - id: black

Cài đặt:

pip install pre-commit
pre-commit install  # kích hoạt hook trong repo

Mỗi lần commit, framework tự chạy toàn bộ hooks đã cấu hình. File hook chỉ cần cài 1 lần cho cả team.

Các trường hợp sử dụng thực tế

Case Hook Tool Mục đích
Format code pre-commit black, ruff Đảm bảo style nhất quán
Phát hiện secret pre-commit detect-secrets Chặn API key trong commit
Run test pre-commit pytest Chặn commit nếu test fail
Update README pre-commit markdownlint Kiểm tra docs syntax
Validate JSON pre-commit check-json Chặn JSON lỗi
Bản đồ pre-push custom script Kiểm tra branch tên trước push
Server infrastructure representing version control backend
Server infrastructure representing version control backend

Nhóm kỹ thuật tại pre-commit duy trì 400+ hooks cho mọi ngôn ngữ. Cài đặt một hook mới chỉ cần thêm 5 dòng vào .pre-commit-config.yaml.

Tránh pitfall phổ biến

  • Không chạy test chậm trong pre-commit: Test unit (60s) nên để ở CI.
  • Bỏ qua non-staged files: Hook chỉ nên check git diff --cached — files đã stage, không phải toàn repo.
  • Bypass emergency: git commit --no-verify vẫn dùng được khi cần. Đừng tạo hook không thể bỏ qua.
  • Version pin: Luôn pin rev trong pre-commit config — tránh hook behavior thay đổi đột ngột.

Pre-push hook: Kiểm tra branch naming

Pre-push hook chạy sau khi user gõ git push nhưng trước khi data rời khỏi local. Ví dụ: enforce branch naming convention:

#!/bin/bash
# .git/hooks/pre-push

while read local_ref local_sha remote_ref remote_sha; do
    branch=""
    
    if [[ ! "" =~ ^(feature|fix|hotfix|release)/[a-z0-9-]+$ ]]; then
        echo "❌ Branch name "" không đúng quy ước."
        echo "   Đúng: feature/ticket-id-description"
        echo "   Ví dụ: feature/JIRA-123-add-login"
        exit 1
    fi
done
exit 0

Hook này đảm bảo tất cả branches tuân theo quy ước: feature/, fix/, hotfix/, release/ + ticket ID + mô tả. Team 20 người sẽ không bao giờ có branch tên test hay updated.

Post-commit hook: Auto-generate changelog

Post-commit hook chạy sau mỗi commit thành công. Ví dụ tự động append commit vào changelog:

#!/bin/bash
# .git/hooks/post-commit

COMMIT_MSG=
COMMIT_HASH=
DATE="2026-09-12"

echo "- []  ()" >> CHANGELOG.md
echo "✅ Changelog updated"

Mỗi commit tự động ghi vào CHANGELOG.md — không cần chạy conventional commits tooling riêng.

Tích hợp với CI/CD

Git hooks bổ sung cho CI chứ không thay thế CI. Hooks kiểm tra nhanh ở local (lint, syntax); CI kiểm tra toàn diện (test suite, security scan, integration test). Pipeline tối ưu:

  1. Pre-commit: Ruff lint (2s), format check (1s) — local only
  2. Pre-push: Unit tests (10s), branch name check (0s) — local only
  3. CI pipeline: Integration tests (2min), security scan (5min), build (3min) — CI only

Khi developer push code đã qua hooks, CI pipeline nhanh hơn vì code đã sạch. Tránh tình huống CI fail vì lỗi lint mà pre-commit đã catch.

Kết luận

Git hooks là “bức tường cuối cùng” trước khi code xấu vào repo. pre-commit framework giúp quản lý tập trung, version control, và triển khai team-wide. Khi setup đúng, developer chỉ cần viết code — chất lượng tự động được đảm bảo ở từng commit. Cài đặt pre-commit install mất 30 giây nhưng ngăn hàng giờ debug sau này.

Terminal showing git hook validation output
Terminal showing git hook validation output

Nguồn tham khảo

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

Hướng Dẫn Fish Shell: Terminal Lành Mạnh Thay Thế Bash Trên Linux

Fish Shell là gì? Fish (Friendly Interactive Shell) là một Unix shell miễn phí và mã nguồn mở, được thiết kế để thân thiện và dễ sử dụng hơn Bash….

Xem thêm

Quản Lý Dotfiles Với Chezmoi: Đồng Bộ Từ Nhiều Máy

Chezmoi là gì? Chezmoi là công cụ quản lý dotfiles mã nguồn mở viết bằng Go, giúp version control, sync và deploy cấu hình cá nhân (dotfiles) trên nhiều máy…

Xem thêm

Tailscale VPN Mesh: Kết Nối Mạng An Toàn Từ Mọi Nơi

Tailscale là giải pháp VPN mesh dựa trên WireGuard cho phép kết nối tất cả thiết bị của bạn thành một mạng an toàn duy nhất. Với Tailscale, bạn không…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất