Advanced
Pertemuan 27
Git Hooks & Husky
Tujuan Pembelajaran
- Memahami konsep dan jenis-jenis Git hooks
- Mampu membuat pre-commit hook manual
- Mengenal Husky sebagai tool manajemen hooks modern
- Memahami lint-staged untuk optimasi hooks
Materi Inti
A. Git Hooks — Script Otomatis
Git hooks adalah script yang berjalan otomatis saat event tertentu terjadi di Git. Hooks tersimpan di folder .git/hooks/ dan bisa digunakan untuk menjaga kualitas kode.
# Lokasi hooks
ls .git/hooks/
# pre-commit.sample, commit-msg.sample, pre-push.sample, dll
Jenis-jenis hooks yang sering digunakan:
| Hook | Kapan Berjalan | Kegunaan |
|---|---|---|
pre-commit | Sebelum commit dibuat | Linter, format kode, cek secrets |
commit-msg | Setelah pesan commit ditulis | Validasi format pesan commit |
pre-push | Sebelum push ke remote | Jalankan test, cek branch |
post-merge | Setelah merge selesai | Install dependencies baru |
prepare-commit-msg | Sebelum editor pesan commit dibuka | Template pesan commit |
Aturan penting:
- Hook harus executable (
chmod +x) - Exit code 0 = sukses (lanjutkan operasi)
- Exit code 1 (atau non-zero) = gagal (batalkan operasi)
- Hooks di
.git/hooks/tidak ter-track oleh Git (tidak ikut di-push)
B. Membuat Pre-Commit Hook Manual
# Contoh pre-commit hook: cek console.log dan .env
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
echo "=== Pre-commit Check ==="
# Cek 1: Apakah ada console.log yang tertinggal?
if grep -r "console.log" --include="*.js" .; then
echo "ERROR: Masih ada console.log! Hapus sebelum commit."
exit 1
fi
# Cek 2: Apakah file .env ikut ter-commit?
if git diff --cached --name-only | grep -q ".env"; then
echo "ERROR: File .env tidak boleh di-commit!"
exit 1
fi
echo "Semua pengecekan LULUS!"
exit 0
EOF
chmod +x .git/hooks/pre-commit
C. Commit-msg Hook
# Validasi format Conventional Commits
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/sh
commit_msg=$(cat "$1")
# Cek format: tipe: deskripsi
if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|ci|perf|build|revert)(\(.+\))?: .+"; then
echo "ERROR: Pesan commit harus mengikuti format Conventional Commits!"
echo "Contoh: feat: tambah halaman login"
echo "Contoh: fix(auth): perbaiki validasi email"
exit 1
fi
echo "Pesan commit valid!"
EOF
chmod +x .git/hooks/commit-msg
D. Setup Husky (Modern Approach)
Masalah hook manual: file di .git/hooks/ tidak ikut ter-track Git, sehingga tidak bisa di-share ke tim. Husky menyelesaikan masalah ini dengan menyimpan hooks di folder .husky/ yang bisa di-commit.
# Inisialisasi project Node.js
npm init -y
# Install Husky dan lint-staged
npm install --save-dev husky lint-staged
# Setup Husky
npx husky init
# Buat pre-commit hook via Husky
echo "npx lint-staged" > .husky/pre-commit
E. Konfigurasi lint-staged
lint-staged hanya menjalankan linter pada file yang ada di staging area (yang di-git add), bukan seluruh project. Ini jauh lebih cepat.
Tambahkan di package.json:
{
"lint-staged": {
"*.js": ["eslint --fix", "prettier --write"],
"*.css": ["prettier --write"],
"*.html": ["prettier --write"]
}
}
Alur kerja dengan Husky + lint-staged:
git add file.js
git commit -m "feat: tambah fitur"
|
v
Husky trigger .husky/pre-commit
|
v
npx lint-staged
|
v
ESLint + Prettier hanya pada file.js (yang di-staged)
|
v
Jika LULUS -> commit berhasil
Jika GAGAL -> commit dibatalkan
Demonstrasi Live
mkdir proyek-hooks && cd proyek-hooks && git init
npm init -y
# Buat pre-commit hook manual
mkdir -p .git/hooks
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
echo "=== Pre-commit Check ==="
# Cek file .env tidak ikut ter-commit
if git diff --cached --name-only | grep -q ".env"; then
echo "ERROR: File .env tidak boleh di-commit!"
exit 1
fi
# Cek tidak ada TODO yang tertinggal
if git diff --cached | grep -q "TODO"; then
echo "WARNING: Ada TODO di kode yang akan di-commit"
echo "(commit tetap dilanjutkan sebagai warning)"
fi
echo "Pre-commit check PASSED!"
EOF
chmod +x .git/hooks/pre-commit
# Test 1: Coba commit file .env (harus gagal)
echo "SECRET=abc123" > .env
git add .env
git commit -m "test: coba commit .env"
# Output: ERROR: File .env tidak boleh di-commit!
# Test 2: Commit file normal (harus berhasil)
git reset HEAD .env
echo ".env" > .gitignore
echo "console.log('hello')" > app.js
git add .gitignore app.js
git commit -m "feat: tambah .gitignore dan app.js"
# Output: Pre-commit check PASSED!
Latihan Praktik
Latihan: Setup Git Hooks Lengkap
mkdir proyek-hooks-latihan && cd proyek-hooks-latihan && git init
npm init -y
# Langkah 1: Buat pre-commit hook yang mengecek:
# - Tidak ada file .env
# - Tidak ada console.log di file .js
# - File tidak lebih dari 100 baris
mkdir -p .git/hooks
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
echo "=== Pre-commit Checks ==="
PASS=true
# Cek 1: File .env
if git diff --cached --name-only | grep -q ".env"; then
echo "GAGAL: File .env terdeteksi!"
PASS=false
fi
# Cek 2: console.log
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')
if [ -n "$FILES" ]; then
for f in $FILES; do
if grep -q "console.log" "$f"; then
echo "GAGAL: console.log ditemukan di $f"
PASS=false
fi
done
fi
if [ "$PASS" = true ]; then
echo "LULUS: Semua pengecekan OK!"
exit 0
else
echo "Commit dibatalkan. Perbaiki error di atas."
exit 1
fi
EOF
chmod +x .git/hooks/pre-commit
# Langkah 2: Buat commit-msg hook
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/sh
msg=$(cat "$1")
if ! echo "$msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|ci): .+"; then
echo "GAGAL: Format pesan commit salah!"
echo "Gunakan: feat|fix|docs|style|refactor|test|chore|ci: deskripsi"
exit 1
fi
EOF
chmod +x .git/hooks/commit-msg
# Langkah 3: Test hooks
echo ".env" > .gitignore
echo "function hello() { return 'hello'; }" > app.js
git add . && git commit -m "feat: setup project"
# Harus BERHASIL
echo "console.log('debug')" > debug.js
git add debug.js
git commit -m "feat: tambah debug"
# Harus GAGAL karena console.log
git reset HEAD debug.js && rm debug.js
Tugas Mandiri
- Buat pre-commit hook yang mengecek minimal 3 hal berbeda (misalnya: .env, console.log, file size)
- Buat commit-msg hook yang memvalidasi format Conventional Commits
- (Opsional) Setup Husky di project Node.js dan konfigurasi lint-staged
- Baca dokumentasi Husky: https://typicode.github.io/husky/