Git Hook ile Kalite Kapısı: pre-commit Kurulumu

Git Hook ile Kalite Kapısı: pre-commit Kurulumu

Kod incelemesinde tartışılan şeylerin çoğu makinenin işi: boşluk, sıralama, unutulmuş debug satırı, yanlışlıkla eklenmiş anahtar. Bunları commit anında yakalamak, insan dikkatini asıl işe bırakıyor.

Git hook kalite kapısı kurmak, kod incelemelerini gereksiz tartışmadan kurtarmanın en ucuz yolu. İnceleme yorumlarınıza bakın: "boşluk fazla", "burada var_dump kalmış", "import sırası bozuk". Bunların hiçbiri insan dikkati gerektirmiyor. Makineye devredildiğinde inceleme, gerçekten insan gerektiren şeye — kodun doğru şeyi yapıp yapmadığına — odaklanabiliyor.

Git hook aşamalarında yapılacak kontroller
Kural: hızlı kontroller commit anında, yavaş olanlar push anında, en yavaşları sunucuda.

Hook nedir, ne zaman çalışır?

Git, belirli olaylarda depodaki betikleri çalıştırır. Üçü pratikte işe yarar:

  • pre-commit — commit oluşturulmadan hemen önce. Sıfır çıkış kodu dönmezse commit iptal edilir.
  • commit-msg — mesaj yazıldıktan sonra. Mesaj biçimini denetlemek için.
  • pre-push — uzak depoya göndermeden önce. Biraz daha yavaş kontroller buraya sığar.

Sıralama önemli: her kontrolü pre-commit'e yığmak en yaygın hata. Commit, günde onlarca kez yapılan bir işlem; oraya koyduğunuz her saniye günde dakikalara dönüşüyor.

Zaman bütçesi

Pratikte işleyen dağılım şu:

AşamaBütçeUygun kontroller
pre-commit< 2 saniyeBiçimlendirme, sözdizimi, sır taraması
commit-msganlıkMesaj biçimi
pre-push< 30 saniyeHızlı birim testleri, statik analiz
CI sunucusudakikalarTüm testler, güvenlik taraması, derleme

Bu bütçeyi aşan her kontrol, geliştiricileri --no-verify kullanmaya iter. Kapının atlanabilir olması sorun değil; düzenli olarak atlanıyor olması sorundur.

Ekipte paylaşılabilir kurulum

.git/hooks klasörü depoya dâhil değildir; oraya yazdığınız betik yalnızca sizde çalışır. Çözüm, hook'ları depoda izlenen bir klasöre koyup Git'i oraya yönlendirmek:

Bash
mkdir -p .githooks
git config core.hooksPath .githooks
chmod +x .githooks/*

Ayar komutunu kurulum betiğinize veya README'nin ilk adımına koyun. Böylece depoyu klonlayan herkes aynı kapıyı kuruyor ve hook'lar sürüm kontrolüyle birlikte gelişiyor.

İşe yarayan bir pre-commit

Aşağıdaki betik dört şeyi kontrol ediyor ve yalnızca hazırlanmış dosyalara bakıyor — bu, süreyi saniyelerde tutan asıl ayrıntı:

Bash
#!/bin/sh
# .githooks/pre-commit

DOSYALAR=$(git diff --cached --name-only --diff-filter=ACM | grep '\.php$')
[ -z "$DOSYALAR" ] && exit 0

# 1) Sözdizimi
for f in $DOSYALAR; do
  php -l "$f" > /dev/null || { echo "✗ Sözdizimi hatası: $f"; exit 1; }
done

# 2) Unutulmuş hata ayıklama satırları
if git diff --cached -U0 -- $DOSYALAR | grep -nE '^\+.*(var_dump|dd\(|console\.log)'; then
  echo "✗ Hata ayıklama satırı kalmış."
  exit 1
fi

# 3) Sır sızıntısı (kaba ama etkili)
if git diff --cached -U0 -- $DOSYALAR | grep -nE '^\+.*(AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY)'; then
  echo "✗ Kaynak koda anahtar eklenmiş görünüyor."
  exit 1
fi

# 4) Biçimlendirme (düzeltip yeniden hazırla)
vendor/bin/php-cs-fixer fix --quiet $DOSYALAR 2>/dev/null && git add $DOSYALAR

exit 0

Üçüncü kontrol, tek başına bu kurulumu haklı çıkarıyor. Depoya girmiş bir anahtar, sonradan silinse bile geçmişte kalır; tek çözüm anahtarı iptal edip yenilemektir. Sırların doğru yeri konusunda .env dosyasından sır kasasına geçiş yazısına bakabilirsiniz.

Commit mesajı denetimi

Mesaj biçimini standartlaştırmak, sürüm notlarını otomatik üretebilmenin ön koşulu:

Bash
#!/bin/sh
# .githooks/commit-msg
DESEN='^(feat|fix|docs|refactor|test|chore)(\([a-z0-9-]+\))?: .{10,}'
grep -qE "$DESEN" "$1" || {
  echo "✗ Mesaj biçimi: tip(kapsam): en az 10 karakter açıklama"
  exit 1
}

Bu kuralı koymadan önce ekiple konuşun; tek taraflı dayatılan biçim kuralları genellikle ilk haftadan sonra atlanmaya başlıyor. İyi bir commit mesajının neden önemli olduğu konusunda Git ile çalışma yazısında ayrıntı var.

pre-push: testin doğru yeri

Testleri commit'e değil push'a bağlayın. Geliştirici gün içinde onlarca commit atar ama günde birkaç kez push eder; testin oraya taşınması hem bütçeye uyuyor hem de bozuk kodun uzak depoya çıkmasını engelliyor.

Bash
#!/bin/sh
# .githooks/pre-push — yalnızca hızlı takım
vendor/bin/phpunit --testsuite=unit --stop-on-failure || {
  echo "✗ Birim testleri başarısız. Göndermeden önce düzeltin."
  exit 1
}

Hızlı takımı gerçekten hızlı tutun. Veritabanına giden testler bu aşamaya değil CI'ya ait; ayrımın nasıl kurulacağı için hangi testi ne zaman yazmalı yazısı yardımcı olur.

Hook'lar bir güvenlik sınırı değildir. Yerel makinede çalışırlar, kapatılabilirler ve depoyu klonlayan biri hiç kurmayabilir. Bir kontrolün kesinlikle uygulanması gerekiyorsa yeri sunucudur: birleştirmeyi engelleyen zorunlu CI adımı olarak tanımlayın. Hook, hatayı erken göstermek içindir; garanti etmek için değil.

Kademeli devreye alma

Tüm kuralları bir gecede zorunlu yapmak, mevcut kod tabanında yüzlerce ihlalle karşılaşmak demek. Daha az sancılı yol: kuralları önce yalnızca değişen dosyalara uygulayın. Kod tabanı zamanla, dokunuldukça temizlenir; kimse "43 dosyada biçim düzeltmesi" başlıklı bir değişiklik incelemek zorunda kalmaz.

Sonuç

Git hook kalite kapısı, ekibe getirdiği yükün çok üstünde bir getiri sağlıyor: kurulumu bir öğleden sonra, bakımı neredeyse sıfır. Kritik olan iki şey var — kontrolleri doğru aşamaya yerleştirmek ve commit anını iki saniyenin altında tutmak. Bu ikisi sağlandığında hook'lar görünmez hâle geliyor; yalnızca gerçekten bir hata olduğunda konuşuyorlar. Dallanma tarafını da düzenlemek isterseniz trunk-based mi Git Flow mu yazısına göz atın.

Hook türlerinin tam listesi: Git — githooks belgeleri.

Beğeniniz benzer içerikleri öne çıkarmamıza yardımcı olur.

Sık Sorulan Sorular

Varsayılan olarak .git/hooks klasörü depoya dâhil değildir, yani hook'lar kopyalanmaz. Çözüm, hook betiklerini depoda izlenen bir klasörde tutup core.hooksPath ayarını oraya yönlendirmek. Böylece klonlayan herkes tek komutla aynı kapıyı kurmuş oluyor.

Yanlış kurulursa yavaşlatır. Pratik sınır şu: commit anındaki kontroller iki saniyeyi geçmemeli. Testleri pre-commit'e koyan ekipler kısa sürede --no-verify ile hook'u atlamaya başlıyor, yani kapı fiilen kapanıyor. Yavaş kontroller pre-push ve CI aşamalarına ait.

Evet ve edilmelidir. Tüm projeyi her commit'te taramak büyük depolarda dakikalar sürer. git diff --cached ile yalnızca hazırlanmış dosyaları alıp kontrolü onlara uygulamak, süreyi saniyelere indiriyor.

Kesinlikle. Hook'lar yerel makinede çalışır ve atlanabilir; güvenlik sınırı değil, kolaylık aracıdırlar. Zorunlu kontroller sunucuda, birleştirmeyi engelleyecek şekilde tanımlanmalı. İkisi birbirinin yerine değil, tamamlayıcısıdır.

S
superadmin

Bu yazıyı hazırladı. Sorularınız için iletişim sayfasından ulaşabilirsiniz.

Yorumlar (0)

Bu yazıya henüz yorum yapılmamış. İlk yorumu siz yazın!

Yorum Yaz

Yorumunuz onaylandıktan sonra yayınlanır. Ekibimiz gerekirse konuyla ilgili bir yanıt da paylaşır.

En az 10 karakter.