Skip to content

Thực hành: Git Hooks & Automation

🎯 Mục tiêu

🎯 Sau bài thực hành này, bạn sẽ:

  • Hiểu các loại Git hooks và thời điểm kích hoạt
  • Viết được pre-commit hook tự động kiểm tra code
  • Biết cách chia sẻ hooks với team qua Husky

Phần 1: Trắc nghiệm

🧠 Quiz

Câu 1: Hook pre-commit chạy vào thời điểm nào?

  • [ ] A) Sau khi commit đã được tạo thành công
  • [x] B) Trước khi Git tạo commit — nếu hook trả về exit code khác 0, commit bị hủy
  • [ ] C) Trước khi push code lên remote
  • [ ] D) Khi mở editor để viết commit message

💡 Giải thích: pre-commit chạy trước khi Git tạo commit object — dùng để lint, format, kiểm tra file cấm. Exit code 0 = cho phép, khác 0 = chặn.

🧠 Quiz

Câu 2: Git hooks được lưu ở đâu trong repository?

  • [x] A) Thư mục .git/hooks/ — mỗi hook là một file executable
  • [ ] B) File .githooks ở root của repository
  • [ ] C) Trong file .gitconfig của user
  • [ ] D) Trên remote server, tự động tải về khi clone

💡 Giải thích: Hooks nằm trong .git/hooks/. Khi git init, Git tạo sẵn file mẫu đuôi .sample. Bỏ đuôi .sample và thêm quyền execute để kích hoạt. Vì .git/ không track, cần Husky hoặc core.hooksPath để share hooks.

🧠 Quiz

Câu 3: Sự khác biệt giữa pre-commitpre-push hook là gì?

  • [ ] A) Không khác nhau — cả hai đều chạy trước khi code lên server
  • [ ] B) pre-commit chạy trên server, pre-push chạy trên client
  • [x] C) pre-commit kiểm tra trước mỗi commit, pre-push kiểm tra trước khi đẩy lên remote
  • [ ] D) pre-push nhanh hơn vì chỉ kiểm tra file đã thay đổi

💡 Giải thích: pre-commit chạy mỗi lần commit — dùng cho kiểm tra nhanh (lint, format). pre-push chạy ít hơn — phù hợp kiểm tra nặng (test suite, build).

Phần 2: Tìm lỗi sai

🐛 Spot-the-Bug

Tìm lỗi: Pre-commit hook không hoạt động

Developer viết hook chặn console.log nhưng hook không chạy:

bash
# Pre-commit hook - check for console.log
echo "Running pre-commit checks..."
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')
if [ -z "$FILES" ]; then exit 0; fi
for FILE in $FILES; do
  if grep -q "console.log" "$FILE"; then
    echo "ERROR: console.log found in $FILE"; exit 1
  fi
done
exit 0

Câu hỏi: Có 2 vấn đề. Tìm ra không?

Đáp án: (1) Thiếu shebang #!/bin/sh ở dòng đầu. (2) Thiếu quyền execute — cần chmod +x. Thiếu thì Git bỏ qua im lặng.

Phần 3: Bài tập — Viết pre-commit hook

Các bước:

  1. mkdir hook-demo && cd hook-demo && git init
  2. Tạo .git/hooks/pre-commit:
    bash
    #!/bin/sh
    STAGED=$(git diff --cached --name-only)
    for file in $STAGED; do
      if [ -f "$file" ] && grep -qE "TODO FIXME|HACK" "$file"; then
        echo "BLOCKED: $file has forbidden markers"; exit 1
      fi
    done
    exit 0
  3. chmod +x .git/hooks/pre-commit
  4. Test 1 — File hợp lệ → commit thành công. Test 2 — File chứa TODO FIXME → bị chặn

Lưu ý

Trong dự án thực tế, dùng Husky hoặc pre-commit (Python) thay vì hook thủ công — đảm bảo toàn team dùng cùng hooks.