Git hooks to skrypty uruchamiane automatycznie przy operacjach Gita. Pre-commit hook uruchomiony przed każdym commitem eliminuje klasę błędów zanim trafią do historii. Commit-msg wymusza konwencję wiadomości. Pre-push chroni zdalny branch przed broken code. Pokażę jak to skonfigurować w projekcie Magento 2 z DDEV.
Rodzaje hooków
| Hook | Kiedy | Typowe użycie |
|---|---|---|
| pre-commit | Przed zapisem commita | phpcs, phpstan, sprawdzenie debuggerów |
| commit-msg | Po wpisaniu wiadomości | Walidacja formatu Conventional Commits |
| pre-push | Przed wysłaniem na remote | Pełne testy jednostkowe |
| post-merge | Po merge/pull | composer install, cache flush |
pre-commit – phpcs i phpstan
#!/bin/bash
# .git/hooks/pre-commit
set -e
echo "Running PHP CS Fixer..."
files=$(git diff --cached --name-only --diff-filter=ACMR | grep \.php$)
if [ -n "$files" ]; then
vendor/bin/phpcs --standard=PSR12 $files
fi
echo "Running PHPStan..."
if [ -n "$files" ]; then
vendor/bin/phpstan analyse $files --level=8 --no-progress
fi
# Sprawdz czy nie ma var_dump lub dd()
if git diff --cached | grep -E "^\+.*var_dump|^\+.*dd\("; then
echo "ERROR: var_dump() or dd() found in staged files"
exit 1
fi
echo "Pre-commit checks passed!"
commit-msg – walidacja formatu
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG=$(cat "$1")
PATTERN="^(feat|fix|refactor|docs|test|chore|perf)(\([a-z-]+\))?: .{10,72}"
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
echo "ERROR: Commit message format invalid."
echo "Required: type(scope): description (10-72 chars)"
echo "Example: feat(catalog): add product export service"
exit 1
fi
pre-push – testy przed wysłaniem
#!/bin/bash
# .git/hooks/pre-push
BRANCH=$(git symbolic-ref HEAD | sed 's/refs\/heads\///')
# Tylko dla main i develop
if [[ "$BRANCH" == "main" || "$BRANCH" == "develop" ]]; then
echo "Running full test suite before push to $BRANCH..."
vendor/bin/phpunit --testsuite=Unit
fi
Udostępnianie hooków w projekcie
Katalog .git/hooks/ nie jest wersjonowany. Najlepsza praktyka: przechowuj hooki w .githooks/ i konfiguruj ścieżkę.
# Skonfiguruj katalog hooków dla całego projektu git config core.hooksPath .githooks # Lub dodaj do composer.json post-install-cmd: # "git config core.hooksPath .githooks" # "chmod +x .githooks/*"
Integracja z DDEV
#!/bin/bash # .githooks/pre-commit - wersja dla DDEV set -e files=$(git diff --cached --name-only --diff-filter=ACMR | grep \.php$) [ -z "$files" ] && exit 0 # Uruchom phpcs i phpstan wewnątrz kontenera DDEV ddev exec vendor/bin/phpcs --standard=PSR12 $files ddev exec vendor/bin/phpstan analyse $files --level=8 --no-progress echo "All checks passed!"
pre-commit jako narzędzie
# .pre-commit-config.yaml
repos:
- repo: https://github.com/digitalpulp/pre-commit-php
rev: 1.4.0
hooks:
- id: php-lint
- id: php-cs
args: [--standard=PSR12]
- id: php-stan
args: [--level=8]
pip install pre-commit pre-commit install # Teraz hooki uruchamiają się automatycznie przy każdym git commit
Podsumowanie
Hooki Gita to pierwsza linia obrony przed błędami w historii. Pre-commit z phpcs i phpstan eliminuje problemy jakości kodu zanim trafią do repo. Commit-msg wymusza czytelne wiadomości. Przechowywanie hooków w .githooks/ i konfiguracja przez git config core.hooksPath udostępnia je całemu zespołowi. Następny wpis: debugging i ratowanie – bisect, reflog, reset vs revert.
