Tidak suka iklan? Pergi Bebas Iklan Hari ini

Git Hooks Pre-commit, Pre-push, dan Menghentikan Kode Buruk di Pintu Masuk

Diperbarui pada

Hook pre-commit, commit-msg, dan pre-push adalah skrip shell yang dijalankan sebelum Git menulis komit atau mengirimkan push. Berikut cara menghubungkannya untuk menangkap kegagalan pemeriksaan, pesan komit yang buruk, dan rahasia yang terlepas — dengan contoh nyata yang bisa Anda gunakan sekarang.

Git Hooks: Pre-commit, Pre-push, and Stopping Bad Code at the Door 2
IKLAN · HAPUS?

Git menyediakan hook — skrip shell yang dijalankan pada titik-titik tertentu dalam alur kerja Anda. Sebagian besar repositori memiliki mereka yang berada dalam keadaan mati di .git/hooks/ sebagai .sample file. Sebagian besar pengembang mengabaikannya sampai commit yang rusak atau kunci API yang terbuka membuat mereka berharap mereka tidak melakukannya.

Ini mencakup tiga hook yang perlu dihubungkan pada setiap proyek: pre-commit, commit-msgdan pre-push. Setiap satu menangkap kelas kesalahan yang berbeda. Setiap satu adalah skrip shell yang dapat Anda salin dan gunakan hari ini.

Di mana hook berada

Setiap repositori git memiliki sebuah .git/hooks/ direktori. Jalankan ls .git/hooks/ dan Anda akan melihat file contoh. Git mengabaikan apa pun yang memiliki .sample ekstensi. Untuk mengaktifkan hook, hilangkan ekstensi dan buat file tersebut dapat dieksekusi:

cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

Kontaknya sederhana: keluarkan 0 dan git melanjutkan. Keluarkan nilai non-nol dan git menghentikan proses, mencetak apa pun yang Anda tulis ke stderr.

pre-commit: hook bernilai tinggi Anda

Pre-commit berjalan setelah Anda mengetik git commit tetapi sebelum objek commit ditulis. Ini tidak dapat melihat pesan commit — itu belum ditulis. Yang dilakukan adalah memeriksa file yang sudah dipilih dan menolak jika sesuatu terlihat salah. bisa Detail penting: gunakan

untuk mendapatkan hanya file yang benar-benar dipilih. Meninjau seluruh proyek pada setiap commit akan lambat dan menampilkan masalah yang tidak Anda buat. git diff --cached --name-only Contoh peninjau (ESLint)

flag melewatkan file yang dihapus — tidak perlu mencoba meninjau sesuatu yang baru saja dihapus.

#!/bin/sh
# Lint only staged JS files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')

if [ -z "$STAGED_FILES" ]; then
  exit 0
fi

echo "Running ESLint on staged files..."
echo "$STAGED_FILES" | xargs ./node_modules/.bin/eslint

if [ $? -ne 0 ]; then
  echo "ESLint failed. Fix errors before committing."
  exit 1
fi

exit 0

Itu --diff-filter=ACM Contoh pemindaian rahasia

Pemindaian pola yang tajam yang menangkap kesalahan yang jelas — kunci API yang ditulis secara langsung, kata sandi di file konfigurasi yang diserahkan secara tidak sengaja:

Untuk proyek selain proyek sederhana, gabungkan ini dengan pemindaian khusus.

#!/bin/sh
# Block commits with obvious secrets
PATTERNS="(AWS_SECRET|api_key\s*=|password\s*=|PRIVATE KEY)"

if git diff --cached | grep -qiP "$PATTERNS"; then
  echo "Potential secret detected in staged changes. Aborting commit."
  exit 1
fi

exit 0

detect-secrets dari Yelp bekerja baik sebagai hook pre-commit — ini mempertahankan file dasar sehingga string yang ditandai sebelumnya tidak menghambat setiap commit. trufflehog lebih baik digunakan untuk pemindaian sejarah setelah itu atau dijalankan dalam CI. commit-msg: memaksa format pesan

Hook ini menerima satu argumen: jalur ke file sementara yang berisi draft pesan commit Anda. Baca, validasi, dan keluarkan 1 untuk menolak. File tersebut dapat dibaca — Anda bisa menormalisasi pesan daripada menolaknya, meskipun hal ini mengejutkan orang pertama kali.

Memaksa

Conventional Commits format adalah penggunaan paling umum. Manfaatnya adalah log perubahan yang otomatis, output yang mudah dibaca, dan pipeline CI yang dapat memarsing tipe commit untuk menentukan apa yang harus dirilis: Ini tidak akan menangkap pesan format yang valid tetapi tetap tidak bermakna seperti git log . Itu adalah masalah budaya, bukan masalah alat.

#!/bin/sh
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")

# type(scope): description — scope is optional
PATTERN="^(feat|fix|chore|docs|style|refactor|test|perf|ci|build|revert)(\(.+\))?: .{1,72}"

if ! echo "$COMMIT_MSG" | grep -qP "$PATTERN"; then
  echo ""
  echo "Invalid commit message. Use Conventional Commits format:"
  echo "  type(scope): short description"
  echo ""
  echo "Valid types: feat, fix, chore, docs, style, refactor, test, perf, ci, build, revert"
  echo "Example:     feat(auth): add OAuth2 login flow"
  echo ""
  echo "Your message: $COMMIT_MSG"
  exit 1
fi

exit 0

pre-push: pintu keluar sebelum tujuan fix: fix thingsPre-push berjalan setelah

diaktifkan tetapi sebelum data dikirim ke remote. Ini menerima nama remote dan URL melalui stdin. Ini adalah tempat untuk uji coba — bukan peninjau (yang berjalan di pre-commit), tetapi uji coba yang memverifikasi perilaku.

Satu kebenaran keras: jika suite uji Anda membutuhkan lebih dari 60–90 detik, orang akan menggunakan git push . Jalankan hanya uji unit cepat di sini. Uji integrasi dan E2E harus berada di CI di mana lambat diterima. Hook yang lambat cukup untuk mengabaikan justru lebih buruk daripada tidak ada hook.

#!/bin/sh
echo "Running tests before push..."

npm test

if [ $? -ne 0 ]; then
  echo "Tests failed. Push aborted."
  exit 1
fi

exit 0

Mengabaikan hook — dan kapan itu sesuai --no-verifyKedua flag ini ada karena alasan tertentu. Hook yang rusak yang menghambat perbaikan darurat adalah hal yang membuat seluruh tim menolak konsep git hook. Gunakan

ketika Anda memiliki alasan yang sah: hook yang salah berjalan pada file yang tidak terkait, atau situasi darurat di mana perbaikan lebih penting daripada pintu.

git commit --no-verify
git push --no-verify

Jika Anda sering menggunakan itu, maka hook perlu disesuaikan. Pelaku paling umum: berjalan terlalu lambat, gagal pada file yang tidak berubah, atau hasil positif dari pola yang belum pernah Anda bersihkan. --no-verify Membagikan hook dengan tim Anda

adalah lokal pada setiap salinan — secara sengaja tidak disimpan dalam repositori. Dua pendekatan untuk membuat hook tetap:

Pilihan 1: core.hooksPath

.git/hooks/ Simpan hook di direktori yang disimpan (misalnya,

), lalu petakan git ke lokasi tersebut:

Untuk mengotomatisasi ini bagi salinan baru, tambahkan sebuah .githooks/skrip ke

git config core.hooksPath .githooks

— npm menjalankannya secara otomatis saat prepare Jadikan skrip tersebut dapat dieksekusi, simpan di repositori, dan siapa pun yang melakukan salinan dan menjalankan package.json akan mendapatkan hook yang dikonfigurasi secara otomatis. npm install:

{
  "scripts": {
    "prepare": "git config core.hooksPath .githooks"
  }
}

Pilihan 2: Husky npm install Husky

adalah pilihan standar untuk proyek JavaScript/Node. Ini menangani

penghubungan untuk Anda dan memberikan setiap hook file sendiri di Lalu tambahkan hook sebagai skrip shell biasa: core.hooksPath Husky 9 (diluncurkan awal 2024) menghapus konfigurasi JSON secara total, menggantinya dengan skrip shell murni. Lebih sederhana daripada versi v4/v8 untuk pengaturan baru, tetapi migrasi dari Husky 4 adalah perubahan yang mengganggu yang kurang ditekankan dalam panduan migrasi resmi — format lama .husky/:

npx husky init

tidak lagi berfungsi sama sekali. Jika Anda memperbarui repositori yang ada, alokasikan waktu untuk itu.

echo "npm test" > .husky/pre-push
chmod +x .husky/pre-push

Repositori non-JavaScript lebih baik dilayani oleh pendekatan .huskyrc . Tidak ada alasan untuk mengunduh ketergantungan Node hanya untuk pengelolaan hook.

Uji perbedaan sebelum hook dijalankan core.hooksPath menampilkan perubahan yang dipilih di terminal. Saat Anda membandingkan dua versi file konfigurasi atau memeriksa apa yang benar-benar diubah oleh refactor di berbagai edit, perbandingan visual lebih cepat dibaca.

IO Tools’ Text Diff

git diff --cached memungkinkan Anda menempelkan dua versi dan melihat persis apa yang berubah — berguna saat Anda ingin meninjau apa yang masuk ke commit sebelum hook dijalankan. Git hooks adalah salah satu alat otomasi yang hidup sepenuhnya dalam alur kerja Anda — tidak perlu akun CI, tidak perlu layanan tambahan, tidak ada biaya. Hook pre-commit yang menolak kegagalan peninjauan sama relabelnya seperti skrip shell yang Anda tulis. Ini adalah fitur: Anda dapat membaca, memperbaiki, dan mengubahnya dalam satu menit. Hubungkan tiga hook di atas dan Anda telah menutup celah terbesar antara “ini bekerja secara lokal” dan “ini bekerja di main.” Git Hooks: Pre-commit, Pre-push, dan Menghentikan Kode Buruk di Pintu 2

Git Hooks: Pre-commit, Pre-push, dan Menghentikan Kode Buruk di Pintu 1

Ingin bebas iklan? Bebas Iklan Hari Ini

Instal Ekstensi Kami

Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat

Ke Ekstensi Chrome Ke Ekstensi Tepi Ke Ekstensi Firefox Ke Ekstensi Opera

Papan Skor Telah Tiba!

Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!

IKLAN · HAPUS?
IKLAN · HAPUS?
IKLAN · HAPUS?

Pojok Berita dengan Sorotan Teknologi

Terlibat

Bantu kami untuk terus menyediakan alat gratis yang berharga

Belikan aku kopi
IKLAN · HAPUS?