🚀 Jak Używać Git do Zarządzania Kodem Źródłowym na Serwerze

Git to obecnie najpopularniejszy system kontroli wersji, który zrewolucjonizował sposób, w jaki programiści zarządzają kodem. Szczególnie przydatny jest w środowisku serwerowym, gdzie umożliwia sprawne wdrażanie zmian, współpracę zespołową i bezpieczne przechowywanie historii rozwoju projektu. W tym kompleksowym przewodniku pokazujemy, jak efektywnie wykorzystać Git na serwerze - od podstaw po zaawansowane techniki automatyzacji wdrożeń.

⚡ Ekspresowe Podsumowanie:

  1. Podstawy serwerowego Git: Konfiguracja repozytorium, modele wdrażania (bare vs. non-bare), bezpieczny dostęp przez SSH.
  2. Workflows wdrożeniowe: Strategie branch, git-flow, GitHub-flow, automatyzacja przy użyciu git hooks.
  3. Zaawansowane techniki: Continuous deployment, git hooks, submoduły, LFS dla dużych plików.
  4. Bezpieczeństwo i wydajność: Kontrola dostępu, GPG, płytkie klonowanie, filtrowanie zawartości.

🗺️ Spis Treści - Twoja Mapa Drogowa


🏁 Wprowadzenie do Git na Serwerze - Czym Się Różni od Lokalnego Użycia?

Git na serwerze pełni inną rolę niż na komputerze dewelopera. Podczas gdy lokalnie Git służy głównie do śledzenia zmian w kodzie i eksperymentowania, na serwerze staje się centralnym punktem koordynacji pracy zespołu oraz narzędziem do wdrażania aplikacji.

Różnice Między Lokalnym a Serwerowym Użyciem Git:

Aspekt Git lokalny Git serwerowy
Główny cel Śledzenie zmian i rozwój kodu Koordynacja zespołu i wdrażanie
Interakcja Bezpośrednia, przez programistę Często zautomatyzowana
Repozytorium Najczęściej non-bare (z working tree) Często bare (bez working tree)
Branches Liczne gałęzie robocze Zwykle ograniczone do głównych gałęzi
Komitowanie Częste, małe zmiany Zmiany są przesyłane, nie tworzone
Czyszczenie Można dowolnie resetować i zmieniać historię Historia powinna być stała, bez zmian

Dwa Główne Modele Repozytoriów Serwerowych:

  1. Bare Repository (Repozytorium "gołe"):

    • Nie zawiera working tree (roboczej kopii plików)
    • Służy wyłącznie jako punkt synchronizacji dla deweloperów
    • Typowo używane jako "centralne" repozytorium
    • Nazwa katalogu kończy się zazwyczaj na .git (np. projekt.git)
  2. Non-bare Repository (Repozytorium standardowe):

    • Zawiera working tree (roboczą kopię plików)
    • Może być używane do wdrażania zmian bezpośrednio na serwerze
    • Pozwala na automatyczne aktualizacje działających aplikacji
    • Wymaga więcej uwagi przy konfiguracji bezpieczeństwa

✨ Pro Tip: W środowisku produkcyjnym często używa się kombinacji obu podejść: repozytorium bare do synchronizacji zespołu oraz non-bare do wdrażania, połączonych automatyzacją.

🛠️ Konfiguracja Git na Serwerze - Podstawy

Poprawna konfiguracja Git na serwerze jest fundamentem efektywnego procesu wdrażania kodu. Przyjrzyjmy się, jak to zrobić krok po kroku.

1. Instalacja Git na Serwerze

Podstawowym krokiem jest instalacja Git na serwerze. W zależności od systemu operacyjnego:

# Dla Ubuntu/Debian
sudo apt update
sudo apt install git

# Dla CentOS/RHEL
sudo yum install git

# Dla Fedora
sudo dnf install git

# Sprawdzenie wersji
git --version

2. Tworzenie Użytkownika dla Git

Dobrą praktyką jest utworzenie dedykowanego użytkownika systemowego do operacji Git:

# Tworzenie użytkownika
sudo adduser git
sudo passwd git

# Opcjonalnie: Ograniczenie dostępu użytkownika tylko do Git
sudo chsh git -s $(which git-shell)

3. Konfiguracja Dostępu SSH

Dostęp SSH to najlepszy sposób na bezpieczną interakcję z repozytoriami Git:

# Na serwerze, jako użytkownik git
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# Skopiuj klucze publiczne deweloperów do authorized_keys
# Dla każdego developera:
echo "ssh-rsa AAAAB3NzaC1yc2E..." >> ~/.ssh/authorized_keys

4. Tworzenie Repozytorium Bare

Centralny punkt synchronizacji dla zespołu:

# Jako użytkownik git
mkdir -p /home/git/repositories
cd /home/git/repositories
git init --bare projekt.git

5. Tworzenie Repozytorium Non-bare dla Wdrożeń

Jeśli chcesz mieć repozytorium do bezpośredniego wdrażania kodu:

# Jako użytkownik z uprawnieniami do katalogu aplikacji
cd /var/www/
git clone /home/git/repositories/projekt.git
cd projekt

6. Podstawowa Konfiguracja Globalna Git

Ustawienie danych użytkownika dla komitów wykonywanych na serwerze:

git config --global user.name "Server Deployment"
git config --global user.email "deploy@example.com"
git config --global core.editor "nano"  # Lub inny preferowany edytor

✨ Pro Tip: Warto utworzyć skrypt inicjalizacyjny, który wykona te kroki automatycznie dla nowych projektów. Oszczędzi to czas i zmniejszy ryzyko błędów konfiguracji.

🔄 Modele Wdrażania z Git - Workflow dla Zespołu

Istnieje kilka popularnych modeli pracy z Git, które sprawdzają się w różnych scenariuszach wdrożeniowych.

1. Centralny Model z Jedną Gałęzią (Podstawowy)

Najprostszy model, zalecany dla małych projektów lub początkujących zespołów:

[Lokalne Repo Dev 1] --push--> [Centralne Repo (bare)] <--pull-- [Serwer Produkcyjny]
    |
    v
[Lokalne Repo Dev 2] --push-->

Kluczowe komendy:

# Developer (po zmianach)
git add .
git commit -m "Opis zmian"
git push origin master

# Na serwerze produkcyjnym
cd /var/www/projekt
git pull origin master

2. Model Git-Flow

Bardziej zaawansowany model, idealny dla większych projektów z zaplanowanymi wydaniami:

                                      /--> [develop] --\
                                     /                  \
[master/main] --> [hotfix] -------->                    \
    ^                                                     \
    |                                                      v
    \---- [release] <---- [feature1, feature2, feature3] --

Konfiguracja na serwerze produkcyjnym:

cd /var/www/projekt
git checkout master  # Produkcja zazwyczaj śledzi master/main
git pull origin master

Konfiguracja na serwerze testowym:

cd /var/www/projekt-test
git checkout develop  # Środowisko testowe śledzi develop
git pull origin develop

3. GitHub/GitLab Flow

Uproszczony model z ciągłą integracją, popularny w projektach z częstymi wdrożeniami:

[master/main] <-- [Pull Request/Merge Request] <-- [feature-branches]

Automatyzacja wdrożeń:

# Hook post-receive w repozytorium bare
#!/bin/bash
TARGET="/var/www/projekt"
GIT_DIR="/home/git/repositories/projekt.git"
BRANCH="main"

while read oldrev newrev ref
do
    # Tylko dla określonej gałęzi
    if [ "$ref" = "refs/heads/$BRANCH" ]; then
        echo "Wdrażanie $BRANCH na $TARGET"
        git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH

        # Dodatkowe kroki po wdrożeniu (np. restart serwera)
        cd $TARGET
        npm install
        pm2 restart app
    fi
done

4. Model z Wersjami Release Tags

Model koncentrujący się na wdrażaniu konkretnych oznaczonych wersji:

[v1.0] --> [v1.1] --> [v1.2] --> [master/main]

Wdrażanie konkretnej wersji:

cd /var/www/projekt
git fetch --all --tags
git checkout tags/v1.2

✨ Pro Tip: Niezależnie od wybranego modelu, warto zainwestować czas w tworzenie automatycznych testów i integrację z systemem CI/CD, aby zapewnić stabilność wdrożeń.

🔄 Automatyzacja Wdrożeń z Git Hooks

Git hooks to potężne narzędzie pozwalające automatyzować proces wdrażania kodu na serwerze.

1. Podstawowe Typy Hooks na Serwerze

Główne hooki używane przy wdrażaniu:

  • pre-receive - uruchamiany przed akceptacją zmian (np. do walidacji)
  • update - podobny do pre-receive, ale uruchamiany dla każdej aktualizowanej gałęzi
  • post-receive - uruchamiany po zakończeniu przesyłania zmian (idealny do wdrożeń)

2. Prosty Hook Post-receive dla Automatycznego Wdrażania

Oto przykład skutecznego hooka do automatycznego wdrażania po każdym pushu:

# Utwórz plik hooks/post-receive w repozytorium bare
#!/bin/bash
DEPLOY_DIR="/var/www/aplikacja"
GIT_WORK_TREE=$DEPLOY_DIR git checkout -f master

# Dodatkowe kroki po wdrożeniu
cd $DEPLOY_DIR

# Przykład dla aplikacji Node.js
npm install
npm run build
pm2 restart app

# Przykład dla aplikacji PHP
php composer.phar install
php artisan migrate --force

# Przykład dla aplikacji Python
pip install -r requirements.txt
python manage.py migrate

# Logi dla debugowania
echo "Wdrożono zmiany z gałęzi master do $DEPLOY_DIR o $(date)" >> /var/log/git-deploy.log

Nadanie uprawień do wykonania:

chmod +x hooks/post-receive

3. Bardziej Zaawansowany Hook dla Wielu Środowisk

Hook obsługujący różne środowiska w zależności od gałęzi:

#!/bin/bash
while read oldrev newrev ref
do
    branch=$(echo $ref | cut -d'/' -f3)

    # Logowanie
    echo "Gałąź: $branch"
    echo "Stara rewizja: $oldrev"
    echo "Nowa rewizja: $newrev"

    # Wdrażanie do różnych środowisk w zależności od gałęzi
    case "$branch" in
        "main"|"master")
            echo "Wdrażanie do produkcji..."
            DEPLOY_DIR="/var/www/produkcja"
            ;;
        "develop")
            echo "Wdrażanie do środowiska testowego..."
            DEPLOY_DIR="/var/www/test"
            ;;
        "staging")
            echo "Wdrażanie do środowiska staging..."
            DEPLOY_DIR="/var/www/staging"
            ;;
        *)
            echo "Gałąź $branch nie jest skonfigurowana do automatycznego wdrażania"
            exit 0
            ;;
    esac

    # Wdrażanie
    GIT_WORK_TREE=$DEPLOY_DIR git checkout -f $branch

    # Dodatkowe kroki po wdrożeniu
    cd $DEPLOY_DIR

    # Przykład dla aplikacji PHP
    php composer.phar install --no-dev
    php artisan migrate --force
    php artisan config:cache
    php artisan route:cache

    # Resetowanie uprawnień jeśli potrzebne
    chown -R www-data:www-data $DEPLOY_DIR

    # Logi
    echo "Wdrożono $branch do $DEPLOY_DIR o $(date)" >> /var/log/git-deploy.log
done

4. Hook do Walidacji i Zabezpieczania Wdrożeń

Hook pre-receive do sprawdzania jakości kodu przed akceptacją:

#!/bin/bash
# Hook pre-receive do walidacji komitów

# Tymczasowy katalog do klonowania
TEMP_DIR=$(mktemp -d)
git clone --quiet $GIT_DIR $TEMP_DIR

while read oldrev newrev ref
do
    branch=$(echo $ref | cut -d'/' -f3)

    # Pomijamy usunięcia gałęzi
    if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then
        echo "Usunięto gałąź $branch, pomijam walidację"
        continue
    fi

    # Sprawdzanie tylko głównej gałęzi
    if [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
        cd $TEMP_DIR

        # Przechodzimy do nowej wersji
        git checkout -q $newrev

        # Przykłady walidacji

        # 1. Uruchamianie testów
        if ! npm test; then
            echo "BŁĄD: Testy nie przeszły. Wdrożenie zatrzymane."
            exit 1
        fi

        # 2. Statyczna analiza kodu
        if command -v eslint &> /dev/null; then
            if ! eslint .; then
                echo "BŁĄD: ESLint znalazł problemy. Wdrożenie zatrzymane."
                exit 1
            fi
        fi

        # 3. Sprawdzanie poprawności składni PHP
        find . -name "*.php" -exec php -l {} \; | grep "Parse error" && {
            echo "BŁĄD: Znaleziono błędy składniowe w plikach PHP. Wdrożenie zatrzymane."
            exit 1
        }
    fi
done

# Sprzątanie
rm -rf $TEMP_DIR
exit 0

✨ Pro Tip: Git hooks są potężnym narzędziem, ale mogą stać się skomplikowane. Rozważ użycie narzędzi CI/CD jak Jenkins, GitLab CI lub GitHub Actions do bardziej zaawansowanych scenariuszy wdrażania.

📦 Zarządzanie Dużymi Plikami i Zależnościami

Efektywne zarządzanie kodem źródłowym to nie tylko sam kod, ale również zasoby, konfiguracje i zależności projektu.

1. Git LFS dla Dużych Plików

Git LFS (Large File Storage) to rozszerzenie Git do zarządzania dużymi plikami binarnymi:

# Instalacja Git LFS na serwerze
sudo apt-get install git-lfs
git lfs install --system

# Konfiguracja użytkownika git do obsługi LFS
sudo -u git git lfs install

# Przykładowe śledzenie dużych plików w repozytorium
git lfs track "*.psd"
git lfs track "*.jpg"
git lfs track "*.mp4"
git add .gitattributes

2. Zarządzanie Modułami Zależnymi (Submodules)

Submoduły Git są przydatne do włączania zewnętrznych repozytoriów:

# Dodawanie submodułu
git submodule add https://github.com/example/library.git libs/library

# Inicjalizacja submodułów po klonowaniu
git submodule update --init --recursive

# Aktualizacja wszystkich submodułów
git submodule update --remote

# Hook do automatycznej aktualizacji submodułów po pullu
cat > .git/hooks/post-merge << 'EOT'
#!/bin/bash
git submodule update --recursive
EOT
chmod +x .git/hooks/post-merge

3. Zarządzanie Wrażliwymi Danymi

Bezpieczne zarządzanie konfiguracjami zawierającymi dane dostępowe:

# Konfiguracja gitconfig do filtrowania plików
git config --global filter.vault.clean "openssl enc -aes-256-cbc -salt -pass file:/path/to/secret.key"
git config --global filter.vault.smudge "openssl enc -d -aes-256-cbc -salt -pass file:/path/to/secret.key"

# Konfiguracja .gitattributes
echo "config/secrets.yml filter=vault" >> .gitattributes

Alternatywnie, używaj bezpiecznych zmiennych środowiskowych:

# W hooks/post-receive
echo 'export DB_PASSWORD="tajne_haslo"' > /var/www/app/.env
echo 'export API_KEY="twoj_klucz_api"' >> /var/www/app/.env

4. Sparse Checkout dla Częściowego Klonowania

Umożliwia klonowanie tylko wybranych części repozytorium:

# Inicjalizacja pustego repozytorium
mkdir projekt-czesciowy && cd projekt-czesciowy
git init
git remote add origin ssh://git@server/home/git/repositories/projekt.git

# Włączenie sparse checkout
git config core.sparseCheckout true

# Określenie, które katalogi chcemy pobrać
echo "src/frontend/" >> .git/info/sparse-checkout
echo "config/" >> .git/info/sparse-checkout

# Pobranie wybranej zawartości
git pull origin master

✨ Pro Tip: W przypadku bardzo dużych repozytoriów, rozważ użycie płytkiego klonowania (git clone --depth 1) do wdrożeń na serwerze. Przyspieszy to proces pobierania bez utraty aktualnego kodu.

🔒 Bezpieczeństwo i Zarządzanie Dostępem

Bezpieczeństwo repozytorium Git na serwerze ma kluczowe znaczenie, szczególnie w środowisku produkcyjnym.

1. Kontrola Dostępu przez SSH

Precyzyjne zarządzanie dostępem do repozytorium:

# Tworzenie pliku konfiguracyjnego dla SSH
sudo nano /etc/ssh/sshd_config

# Dodanie następujących linii dla bezpieczeństwa
PermitRootLogin no
PasswordAuthentication no
AllowUsers git developer1 developer2

Dla bardziej zaawansowanej kontroli dostępu, użyj klucza command w authorized_keys:

# W pliku ~/.ssh/authorized_keys
command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2E...

2. Wdrażanie Polityk Bezpieczeństwa z Git Hooks

Egzekwowanie zasad bezpieczeństwa dla komitów:

# Hook pre-receive do sprawdzania wrażliwych danych
#!/bin/bash

forbidden_patterns=(
    'password\s*=\s*['"'"']?[a-zA-Z0-9]+['"'"']?'
    'secret\s*=\s*['"'"']?[a-zA-Z0-9]+['"'"']?'
    'ACCESS_KEY\s*=\s*['"'"']?[a-zA-Z0-9]+['"'"']?'
    'api_key\s*=\s*['"'"']?[a-zA-Z0-9]+['"'"']?'
)

zero_commit="0000000000000000000000000000000000000000"

while read old_rev new_rev ref; do
    # Pomiń usunięcia gałęzi
    if [ "$new_rev" = "$zero_commit" ]; then
        continue
    fi

    # Sprawdź zmiany
    files_changed=$(git diff --name-only "$old_rev" "$new_rev")

    for file in $files_changed; do
        # Pomiń pliki binarne
        if git check-attr -a -- "$file" | grep -q "binary: set"; then
            continue
        fi

        # Sprawdź każdy wzorzec w zmienionych plikach
        for pattern in "${forbidden_patterns[@]}"; do
            if git show "$new_rev":"$file" | grep -E "$pattern" > /dev/null; then
                echo "BŁĄD BEZPIECZEŃSTWA: Znaleziono potencjalnie wrażliwe dane w pliku $file"
                echo "Proszę usunąć wrażliwe dane i spróbować ponownie."
                exit 1
            fi
        done
    done
done

exit 0

3. Podpisywanie Commitów i Tagów

Weryfikacja autentyczności zmian za pomocą kluczy GPG:

# Generowanie klucza GPG na maszynie developerskiej
gpg --full-generate-key

# Konfiguracja Git do podpisywania komitów
git config --global user.signingkey ID_KLUCZA
git config --global commit.gpgsign true
git config --global tag.gpgsign true

# Eksport klucza publicznego
gpg --armor --export ID_KLUCZA > moj_klucz.asc

# Na serwerze - import klucza
gpg --import moj_klucz.asc

# Weryfikacja podpisów w hook pre-receive
#!/bin/bash
while read old_rev new_rev ref; do
    # Sprawdź podpisy dla wszystkich nowych commitów
    commits=$(git rev-list $old_rev..$new_rev)
    for commit in $commits; do
        if ! git verify-commit $commit; then
            echo "BŁĄD: Commit $commit nie został prawidłowo podpisany"
            exit 1
        fi
    done
done

4. Monitorowanie i Audyt Dostępu

Śledzenie operacji na repozytorium:

# Hook post-receive do logowania operacji
#!/bin/bash
# Log wszystkich pushów
LOG_FILE="/var/log/git/access.log"
DATE=$(date "+%Y-%m-%d %H:%M:%S")
REPO=$(basename $(pwd))
CLIENT_IP=$(echo $SSH_CLIENT | awk '{print $1}')
USER=$USER

while read old_rev new_rev ref; do
    branch=$(echo $ref | cut -d'/' -f3)
    echo "$DATE | $USER | $CLIENT_IP | $REPO | $branch | $old_rev -> $new_rev" >> $LOG_FILE
done

✨ Pro Tip: Rozważ integrację z systemami SIEM (Security Information and Event Management) do monitorowania i alertowania o podejrzanych działaniach w repozytorium, szczególnie w środowiskach produkcyjnych.

📈 Wydajność i Optymalizacja Dużych Repozytoriów

Wraz z rozwojem projektu, repozytorium Git może się rozrastać, co wpływa na wydajność operacji. Oto jak optymalizować duże repozytoria:

1. Płytkie Klonowanie i Filtrowanie Historii

Techniki ograniczania ilości pobieranych danych:

# Płytkie klonowanie (tylko ostatni komit)
git clone --depth 1 git@server:repo.git

# Klonowanie tylko jednej gałęzi
git clone --single-branch --branch develop git@server:repo.git

# Filtrowanie historii po klonowaniu
git filter-branch --prune-empty --tree-filter 'rm -rf large_directory/' HEAD

# Oczyszczanie po filter-branch
git reflog expire --expire=now --all
git gc --prune=now --aggressive

2. Czyszczenie i Kompresja Repozytorium

Regularna konserwacja dla optymalnej wydajności:

# Czyszczenie luźnych obiektów
git gc

# Agresywna optymalizacja (uruchamiaj rzadko)
git gc --aggressive

# Weryfikacja integralności repozytorium
git fsck --full

# Kompresja packfiles
git repack -a -d --depth=250 --window=250

3. Optymalizacja Konfiguracji Git na Serwerze

Dostosowanie ustawień dla lepszej wydajności:

# Globalne ustawienia wydajności
git config --system core.preloadindex true
git config --system core.fsyncobjectfiles true
git config --system gc.auto 256

# Dla bardzo dużych repozytoriów
git config --system pack.windowMemory 100m
git config --system pack.packSizeLimit 100m
git config --system pack.threads 2

# Konfiguracja cache
git config --system core.bigFileThreshold 50m

4. Podzielenie Monolitycznego Repozytorium

Gdy repozytorium staje się zbyt duże, warto rozważyć jego podział:

# Wyodrębnienie podkatalogu do nowego repozytorium
git subtree split -P podkatalog/ -b podkatalog-branch

# Utworzenie nowego repozytorium z wydzieloną gałęzią
mkdir ../nowe-repo
cd ../nowe-repo
git init
git pull ../stare-repo podkatalog-branch

# Usunięcie wydzielonego katalogu ze starego repozytorium
cd ../stare-repo
git rm -rf podkatalog/
git commit -m "Przeniesiono podkatalog do osobnego repozytorium"

✨ Pro Tip: Rozważ użycie narzędzi takich jak Git LFS dla dużych plików binarnych oraz git filter-repo (następca filter-branch) do efektywnego przepisywania historii bez utraty wydajności.

🚀 Wdrażanie Ciągłe (Continuous Deployment) z Git

Git może być centralnym elementem całego procesu continuous deployment, szczególnie w połączeniu z narzędziami CI/CD.

1. Integracja z Systemami CI/CD

Przykładowa konfiguracja GitLab CI/CD w pliku .gitlab-ci.yml:

stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - npm install
    - npm test

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

deploy_production:
  stage: deploy
  script:
    - ssh deploy@server "cd /var/www/app && git pull origin master"
    - ssh deploy@server "cd /var/www/app && npm install --production"
    - ssh deploy@server "cd /var/www/app && pm2 restart app"
  only:
    - master

2. Konfiguracja Webhooks dla Automatycznego Wdrażania

Użycie webhooka do wyzwalania wdrożeń:

# Skrypt PHP odbierający webhook (deploy.php)
<?php
$secret = "tajny_klucz_webhooka";
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE'] ?? '';

// Weryfikacja podpisu
$payload = file_get_contents('php://input');
$calculated = 'sha1=' . hash_hmac('sha1', $payload, $secret);

if (!hash_equals($signature, $calculated)) {
    http_response_code(401);
    die("Unauthorized");
}

// Wykonaj wdrożenie
$output = [];
exec('cd /var/www/app && git pull origin master 2>&1', $output);
exec('cd /var/www/app && composer install --no-dev 2>&1', $output);
exec('cd /var/www/app && php artisan migrate --force 2>&1', $output);

// Zapisz log
file_put_contents(
    '/var/log/webhook-deploy.log',
    date('Y-m-d H:i:s') . ": Wdrożenie wykonane\n" . implode("\n", $output) . "\n\n",
    FILE_APPEND
);

echo "Deployment successful!";

3. Strategie Zero-Downtime Deployment

Wdrażanie bez przestojów:

# Hook post-receive
#!/bin/bash
DEPLOY_DIR="/var/www/app"
RELEASE_DIR="/var/www/releases/$(date +%Y%m%d%H%M%S)"
CURRENT_LINK="/var/www/current"

# Przygotowanie katalogu wydania
mkdir -p $RELEASE_DIR
GIT_WORK_TREE=$RELEASE_DIR git checkout -f master

# Instalacja zależności i budowanie aplikacji
cd $RELEASE_DIR
composer install --no-dev --optimize-autoloader
npm install --production
npm run build
php artisan optimize

# Kopiowanie konfiguracji z shared
ln -sf /var/www/shared/.env $RELEASE_DIR/.env
ln -sf /var/www/shared/storage $RELEASE_DIR/storage

# Migracja bazy danych
php artisan migrate --force

# Przełączenie linku do nowego wydania 
ln -sfn $RELEASE_DIR $CURRENT_LINK

# Czyszczenie cache
php artisan cache:clear
php artisan config:cache

# Restart usług
sudo systemctl reload php7.4-fpm
sudo systemctl reload nginx

# Opcjonalnie: zachowaj tylko 5 ostatnich wydań
cd /var/www/releases
ls -t | tail -n +6 | xargs -I {} rm -rf {}

4. Rollback w Przypadku Błędów

Szybkie wycofywanie nieudanych wdrożeń:

#!/bin/bash
# rollback.sh
RELEASES_DIR="/var/www/releases"
CURRENT_LINK="/var/www/current"

# Znajdź poprzednie wdrożenie
PREVIOUS_RELEASE=$(ls -t $RELEASES_DIR | sed -n 2p)

if [ -z "$PREVIOUS_RELEASE" ]; then
    echo "Nie znaleziono poprzedniego wdrożenia!"
    exit 1
fi

# Przełącz link na poprzednią wersję
ln -sfn $RELEASES_DIR/$PREVIOUS_RELEASE $CURRENT_LINK

# Restart usług
sudo systemctl reload php7.4-fpm
sudo systemctl reload nginx

echo "Wycofano do wersji $PREVIOUS_RELEASE"

✨ Pro Tip: Dla najbardziej zaawansowanych scenariuszy wdrażania, rozważ użycie specjalizowanych narzędzi jak Capistrano, Ansible, Chef czy Kubernetes, które integrują się z Git i oferują zaawansowane funkcje zarządzania wydaniami.

❓ FAQ - Odpowiedzi na Twoje Pytania

Czy można używać Git bez centralnego serwera?
Tak, Git to rozproszony system kontroli wersji, który może działać w pełni lokalnie. Jednak centralny serwer ułatwia współpracę i wdrażanie, szczególnie w zespołach.

Jak zmienić domyślną gałąź master na main na serwerze?

cd /path/to/repo.git
git symbolic-ref HEAD refs/heads/main

Jaka jest różnica między hooks w .git/hooks a hooks w repozytorium bare?
W standardowym repozytorium hooki znajdują się w katalogu .git/hooks, natomiast w repozytorium bare (bez working tree) są w katalogu hooks bezpośrednio w głównym katalogu repozytorium.

Czy można używać Git do wdrażania większych plików binarnych jak obrazy i wideo?
Tak, ale warto rozważyć Git LFS (Large File Storage) dla dużych plików binarnych, aby uniknąć rozrastania się repozytorium i spowolnienia operacji.

Jak bezpiecznie przechowywać hasła i klucze API w repozytorium Git?
Nigdy nie przechowuj wrażliwych danych bezpośrednio w repozytorium. Zamiast tego:

  1. Używaj zmiennych środowiskowych
  2. Korzystaj z narzędzi jak Vault czy AWS Secrets Manager
  3. Przechowuj zaszyfrowane wersje konfiguracji
  4. Używaj plików .env lokalnie (dodanych do .gitignore)

Jak mogę monitorować wydajność repozytorium Git na serwerze?
Monitoruj użycie dysku za pomocą du -sh, regularnie uruchamiaj git gc, używaj narzędzi jak git count-objects -v do śledzenia liczby obiektów, a dla zaawansowanej analizy rozważ narzędzia jak git-sizer.

🏁 Podsumowanie - Dobre Praktyki dla Git na Serwerze

Efektywne zarządzanie kodem źródłowym za pomocą Git na serwerze wymaga zrozumienia kilku kluczowych koncepcji oraz zastosowania sprawdzonych praktyk:

  1. Wybierz odpowiedni model repozytorium

    • Bare repository do synchronizacji zespołu
    • Non-bare repository do wdrażania kodu
  2. Zaimplementuj bezpieczny dostęp

    • Klucze SSH zamiast haseł
    • Ograniczenie dostępu do minimum potrzebnego
    • Podpisywanie komitów dla weryfikacji autentyczności
  3. Automatyzuj procesy z git hooks

    • Użyj post-receive do automatycznego wdrażania
    • Implementuj walidację w pre-receive
    • Dodaj powiadomienia o wdrożeniach
  4. Dbaj o higienę repozytorium

    • Regularne wykonywanie git gc
    • Używanie Git LFS dla dużych plików
    • Odpowiednia struktura branchy i tagów
  5. Wdrażaj strategie bezpiecznego deploymentu

    • Zero-downtime deployment
    • Możliwość szybkiego rollbacku
    • Testy automatyczne przed wdrożeniem
  6. Integruj z ekosystemem DevOps

    • CI/CD dla automatycznych testów i wdrożeń
    • Webhooks do komunikacji między systemami
    • Monitoring dla zapewnienia stabilności

Git na serwerze to znacznie więcej niż narzędzie do przechowywania kodu - to centralna część nowoczesnego procesu rozwoju oprogramowania, która może znacząco przyspieszyć cykl wdrażania, zwiększyć jakość kodu i ułatwić współpracę zespołową.

🚀 Chcesz skonfigurować własny serwer Git?

Sprawdź naszą ofertę serwerów VPS

Profesjonalne serwery do hostingu Git i wdrażania Twoich aplikacji!

Czy ten artykuł był pomocny?

Wróć do listy wpisów

Twoja strona WordPress działa wolno?

Sprawdź nasz hosting WordPress z ultraszybkimi dyskami NVMe i konfiguracją serwera zoptymalizowaną pod kątem wydajności. Doświadcz różnicy już dziś!

Sprawdź ofertę hostingu
30-dniowa gwarancja zwrotu pieniędzy