1.  [Strona główna](/) ›
2.  [Baza wiedzy](/baza-wiedzy/) ›
3.  Git Hooks - automatyzacja deployment

# Git Hooks - automatyzacja deployment przez git push

Opublikowano: 9 kwietnia 2026 · Kategoria: DevOps / VPS

⚡ W skrócie · 10 min czytania

-   Git hooks dla automatyzacji: post-receive hook na serwerze, CI/CD bez zewnętrznych narzędzi, zero-downtime deploy przez symlink swap, porównanie z GitHub Actions.
-   Rodzaje git hooków.
-   Krok 1: Bare repo na serwerze.
-   Krok 2: Hook post-receive.
-   Krok 3: Remote na lokalnej maszynie.

Git hooks to skrypty uruchamiane automatycznie przez git w kluczowych momentach cyklu życia repozytorium. Dzięki nim możesz wdrożyć aplikację na serwer jednym poleceniem `git push production main` - bez GitHub Actions, bez Jenkins, bez żadnej zewnętrznej usługi. Oto jak to skonfigurować krok po kroku.

## Rodzaje git hooków

Git rozróżnia hooki po stronie klienta (lokalne) i po stronie serwera (zdalne). Do automatyzacji deploymentu używamy hooków serwerowych:

Hook

Strona

Kiedy się uruchamia

Typowe zastosowanie

`pre-commit`

Klient

Przed zatwierdzeniem commita

Lint, formatowanie, testy jednostkowe

`pre-push`

Klient

Przed wysłaniem do remote

Testy integracyjne, sprawdzenie branch

`pre-receive`

Serwer

Przed zaakceptowaniem push

Walidacja, wymuszanie konwencji

`post-receive`

Serwer

Po zaakceptowaniu push

**Deploy - checkout, build, restart**

`update`

Serwer

Przed aktualizacją ref-a

Kontrola dostępu per branch

## Krok 1: Bare repo na serwerze

Na serwerze (przez SSH) utwórz repozytorium bare - przechowuje ono historię git, ale nie ma katalogu roboczego z plikami:

```
# Na serwerze (przez SSH)
ssh user@twoj-serwer.pl

# Utwórz katalogi
mkdir -p /home/deploy/app.git
mkdir -p /var/www/app

# Zainicjuj bare repo
cd /home/deploy/app.git
git init --bare

# Sprawdź zawartość - brak katalogu roboczego!
ls
# HEAD  branches/  config  description  hooks/  info/  objects/  refs/
```

## Krok 2: Hook post-receive

Utwórz plik `/home/deploy/app.git/hooks/post-receive`:

```
#!/bin/bash
# /home/deploy/app.git/hooks/post-receive

set -e  # Przerwij przy błędzie

REPO_DIR="/home/deploy/app.git"
WEB_DIR="/var/www/app"
BRANCH="main"

# Odczytaj które gałęzie są pushowane
while read oldrev newrev refname; do
  PUSHED_BRANCH=${refname##refs/heads/}

  if [ "$PUSHED_BRANCH" != "$BRANCH" ]; then
    echo "Pominięto gałąź $PUSHED_BRANCH (deploy tylko z $BRANCH)"
    continue
  fi

  echo "=== Deploy z gałęzi $BRANCH ==="

  # Checkout plików do webroot
  git --work-tree="$WEB_DIR" --git-dir="$REPO_DIR" checkout -f "$BRANCH"

  cd "$WEB_DIR"

  # PHP: instalacja zależności
  if [ -f "composer.json" ]; then
    echo "--- composer install ---"
    composer install --no-dev --optimize-autoloader --quiet
  fi

  # Node.js: instalacja i build
  if [ -f "package.json" ]; then
    echo "--- npm ci && npm run build ---"
    npm ci --production=false
    npm run build
  fi

  # Laravel: migracje i cache
  if [ -f "artisan" ]; then
    echo "--- artisan migrate + cache ---"
    php artisan migrate --force
    php artisan config:cache
    php artisan route:cache
    php artisan view:cache
  fi

  # Restart PHP-FPM (opcjonalnie)
  # sudo systemctl reload php8.2-fpm

  echo "=== Deploy zakończony pomyślnie ==="
done
```

```
# Nadaj uprawnienia wykonywania
chmod +x /home/deploy/app.git/hooks/post-receive
```

## Krok 3: Remote na lokalnej maszynie

Na lokalnym komputerze dodaj serwer jako remote git:

```
# Dodaj remote o nazwie "production"
git remote add production ssh://user@twoj-serwer.pl/home/deploy/app.git

# Wyślij kod i uruchom deploy
git push production main

# Wynik w terminalu:
# === Deploy z gałęzi main ===
# --- composer install ---
# --- artisan migrate + cache ---
# === Deploy zakończony pomyślnie ===
```

## Zero-downtime deploy przez symlink

Standardowy checkout nadpisuje pliki live - przez kilkanaście sekund aplikacja może być w niespójnym stanie. Bezpieczniejsze podejście to symlink swap (wzorzec Capistrano):

```
#!/bin/bash
# post-receive - wersja z symlinkami (zero-downtime)

REPO_DIR="/home/deploy/app.git"
RELEASES_DIR="/var/www/releases"
CURRENT_LINK="/var/www/current"
TIMESTAMP=${$(date +%Y%m%d%H%M%S)}
RELEASE_DIR="$RELEASES_DIR/$TIMESTAMP"

while read oldrev newrev refname; do
  [ "${refname##refs/heads/}" = "main" ] || continue

  # Utwórz katalog dla nowego release
  mkdir -p "$RELEASE_DIR"

  # Checkout do nowego katalogu
  git --work-tree="$RELEASE_DIR" --git-dir="$REPO_DIR" checkout -f main

  cd "$RELEASE_DIR"

  # Build
  composer install --no-dev -q
  php artisan migrate --force
  php artisan config:cache

  # Atomowe przełączenie symlinku (ln -sfn jest atomowe)
  ln -sfn "$RELEASE_DIR" "$CURRENT_LINK"

  echo "Deploy $TIMESTAMP aktywny"

  # Zachowaj tylko 5 ostatnich releases
  ls -dt "$RELEASES_DIR"/* | tail -n +6 | xargs rm -rf
done
```

Nginx serwuje z `/var/www/current/public`. Przełączenie symlinku jest atomowe - użytkownicy nie zauważą przerwy. Rollback to jedno polecenie: `ln -sfn /var/www/releases/POPRZEDNI /var/www/current`.

## Zmienne środowiskowe w hooku

Hook post-receive działa w ograniczonym środowisku - PATH może nie zawierać katalogu z `composer` czy `node`. Kilka zasad:

```
#!/bin/bash
# Na początku hooka - ustaw PATH i zmienne środowiskowe

export PATH="/usr/local/bin:/usr/bin:/bin:/home/deploy/.composer/vendor/bin:$PATH"
export HOME="/home/deploy"
export NVM_DIR="/home/deploy/.nvm"

# Załaduj nvm jeśli używasz Node.js przez nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

# Załaduj .env.production zamiast wbudowywania sekretów w hook
if [ -f "/etc/app/env.production" ]; then
  source /etc/app/env.production
fi
```

## Obsługa błędów i powiadomienia

```
#!/bin/bash
set -e

# Przechwytuj błędy i wysyłaj powiadomienie
trap 'on_error' ERR

on_error() {
  local EXIT_CODE=$?
  echo "BLAD: Deploy nieudany (kod $EXIT_CODE)" >&2

  # Powiadomienie na Slack/Discord
  curl -s -X POST "$SLACK_WEBHOOK_URL" \
    -H "Content-Type: application/json" \
    -d '{"text": "Deploy FAILED na produkcji! Sprawdz logi."}' || true

  exit $EXIT_CODE
}

# Logowanie do pliku
exec >>/var/log/deploy.log 2>&1
echo "[$(date)] Deploy z commita $newrev"
```

## Git Hooks vs GitHub Actions - kiedy co wybrać?

Kryterium

Git Hooks

GitHub Actions

Zależności zewnętrzne

Zero - tylko git i SSH

GitHub account, internet

Szybkość deployu

Bardzo szybki (sekundy)

Wolniejszy (runner startup ~30s)

Koszty

Zero (już masz serwer)

Darmowy dla public repos, płatny dla private

Testy przed deployem

Tylko to co wpiszesz w skrypcie

Pełna macierz (node 18/20/22, Ubuntu/Windows)

Deploy na wiele serwerów

Trudniejszy (SSH w pętli)

Łatwy (matrix lub parallel jobs)

Sekrety i klucze API

Pliki na serwerze (/etc/app/)

GitHub Secrets (szyfrowane)

Rollback

Ręczny symlink lub git checkout

Depends on workflow design

Idealny dla

Małe projekty, hobby, VPS solo

Zespoły, open source, multi-env

Git hooks to świetny wybór dla małych projektów na jednym VPS - zero konfiguracji poza serwerem, zero kosztów, maksymalna kontrola. GitHub Actions warto wybrać gdy potrzebujesz testów na wielu środowiskach, deploymentu na wiele serwerów lub integracji z zewnętrznymi serwisami (Slack, Sentry, Datadog).

## Najczęstsze pytania

Czym jest git hook post-receive? +

Post-receive to skrypt wykonywalny umieszczony w katalogu hooks/ repozytorium bare na serwerze. Git uruchamia go automatycznie po każdym git push - możesz w nim umieścić dowolne polecenia: checkout kodu do webroot, instalację zależności, restart serwera aplikacji. Skrypt działa z uprawnieniami użytkownika który push-uje lub właściciela procesu git na serwerze.

Czym jest repozytorium bare i dlaczego jest potrzebne do deploymentu? +

Repozytorium bare (git init --bare) przechowuje tylko historię git bez kopii roboczej plików. Na serwer push-ujesz do repo bare (np. /home/deploy/app.git), a hook post-receive checkout-uje pliki do osobnego katalogu webroot (np. /var/www/app). Nie można push-ować do zwykłego repozytorium z zaznaczoną gałęzią - git odmówi przyjęcia zmian.

Kiedy wybrać git hooks zamiast GitHub Actions? +

Git hooks sprawdzają się przy: małych projektach z jednym serwerem, braku konta GitHub/GitLab, gdy chcesz mieć 100% kontrolę bez zewnętrznych usług, lub gdy GitHub Actions jest zbyt wolny dla częstych deploymentów. GitHub Actions jest lepszy gdy potrzebujesz: testów na wielu wersjach środowiska, powiadomień Slack/email, równoległych pipeline'ów lub deploy na wiele serwerów jednocześnie.

Jak zrobić rollback po nieudanym deployu przez git hook? +

Najbezpieczniejszy rollback to symlink swap: hook wypakuje kod do katalogu releases/$(date +%s)/, a następnie przełącza symlink current → nowy katalog (ln -sfn). Jeśli cokolwiek zawiedzie - wystarczy ln -sfn releases/poprzedni current i reload Nginx. Alternatywnie: trzymaj poprzednią wersję w /var/www/app.prev i po awarii mv app app.broken && mv app.prev app.

## Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.

Contabo

VPS z pełnym dostępem SSH - idealny do konfiguracji git hooks i własnego CD

Self-hosted CD

[Aktywuj rabat →](/out/contabo/#reklama "Contabo")

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/contabo/)

Mikrus

Tani VPS do testowania git hooks przed wdrożeniem na produkcji

Dev/Test

[Aktywuj rabat →](/out/mikrus/#reklama "Mikrus")

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/mikrus/)

LH.pl

Hosting z SSH i git - gotowe środowisko bez konfiguracji serwera

Managed

[Aktywuj rabat →](/out/lh-pl/#reklama "LH.pl")

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/lh-pl/)

## Powiązane strony

-   [Git deploy na hostingu - GitHub Actions i SFTP](/baza-wiedzy/git-deploy-hosting/)
-   [Node.js Express - deployment na VPS](/baza-wiedzy/nodejs-express-produkcja/)
-   [Nginx - load balancer i reverse proxy](/baza-wiedzy/nginx-load-balancer-konfiguracja/)
-   [Wszystkie artykuły](/baza-wiedzy/)
-   [Git deploy na hostingu - automatyczny deployment przez git push
    
    Jak skonfigurować automatyczny deploy przez git push na hosting? Bare repo, post-receive hook, GitHub Actions + rsync -…
    
    ](/baza-wiedzy/git-deploy-na-hostingu/)
-   [Drone CI - lekki self-hosted CI/CD dla projektów Git
    
    Drone CI: instalacja server i Docker runner, konfiguracja OAuth GitHub/Gitea, plik .drone.yml z stages i steps,…
    
    ](/baza-wiedzy/drone-cicd-konfiguracja/)
-   [GitHub Actions: deployment na VPS - pełny workflow SSH
    
    Kompletny przewodnik po konfiguracji GitHub Actions do automatycznego deploymentu na VPS: SSH, secrets, matrix builds,…
    
    ](/baza-wiedzy/github-actions-deployment-vps/)
-   [Jaki VPS wybrać?](/jaki-vps-wybrac/)

Autor: [Redakcja HostGrade.pl](/autorzy/) Zespół redakcyjny · Aktualizacja: 9 kwietnia 2026

Artykuły HostGrade.pl przygotowuje i aktualizuje redakcja serwisu. Ceny startowe, ceny odnowienia i warunki planów sprawdzamy w cennikach i regulaminach dostawców, a potem liczymy całkowity koszt za 2 lata (cena startowa plus odnowienia). Zasady zbierania danych i liczenia kosztów opisujemy na stronie Metodologia. Linki partnerskie oznaczamy jako #reklama.

[O redakcji i metodologii →](/autorzy/)