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-commit và pre-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

tcpdump là gì: công cụ bắt và đọc gói tin mạng từ dòng lệnh

tcpdump là công cụ dòng lệnh phổ biến nhất thế giới dùng để bắt và phân tích gói tin mạng. Nó dùng thư viện libpcap để chuyển dữ liệu thô…

Xem thêm

VLC media player là gì: trình phát đa năng cho mọi định dạng

VLC media player là trình phát đa năng mã nguồn mở do dự án VideoLAN phát triển, chạy được trên máy tính lẫn điện thoại. Nhờ đọc được gần như…

Xem thêm

ripgrep là gì? Công cụ tìm kiếm nhanh hơn grep trong terminal

ripgrep (rg) là một công cụ tìm kiếm trong dòng terminal được thiết kế để thay thế grep truyền thống, đặc biệt phù hợp với môi trường phát triển phần…

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