Zaoszczędź 15% na wszystkich usługach hostingowych

Sprawdź swoje umiejętności i zdobądź Rabat na dowolny plan hostingowy

Użyj kodu: Skills Rozpocznij
Sekcja
Linux Serwery Wirtualne

Struktura Repozytorium Git: Kompletny Przewodnik Techniczny

Git to rozproszony system kontroli wersji, który przechowuje historię projektu jako skierowany graf acykliczny (DAG) niezmiennych obiektów migawkowych. Każde repozytorium Git zbudowane jest z trzech logicznych stref — katalogu roboczego, indeksu tymczasowego i magazynu obiektów wewnątrz .git/ — oraz zestawu lekkich wskaźników (gałęzie, tagi, zdalne repozytoria), które nawigują po tej historii. Zrozumienie, jak te warstwy ze sobą współdziałają, to różnica między mechanicznym używaniem Git a używaniem go z chirurgiczną precyzją.

Jeśli samodzielnie hostujesz swoje repozytoria na VPS, opanowanie tej wewnętrznej struktury pozwala odzyskiwać dane po awariach, projektować wydajne pipeline’y CI/CD i audytować każdy bajt historii projektu bez polegania na platformach zewnętrznych.

Model trzech stref: jak Git przenosi dane

Zanim zagłębisz się w poszczególne komponenty, przyswój model przepływu danych, który rządzi każdą operacją Git:

Working Directory  -->  Staging Area (Index)  -->  .git/ Object Store
     (edit)               (git add)                  (git commit)

Zmiany przemieszczają się od lewej do prawej podczas budowania commita, a od prawej do lewej podczas przywracania lub resetowania. Każde polecenie Git to w istocie operacja odczytu lub zapisu na jednej lub kilku z tych stref.

Katalog roboczy

Katalog roboczy (zwany również drzewem roboczym) to widok systemu plików projektu w określonym stanie checkout. Gdy uruchamiasz git clone lub git checkout, Git rekonstruuje pliki ze skompresowanych obiektów w .git/objects/ i zapisuje je w tym katalogu.

Pliki w katalogu roboczym istnieją w jednym z czterech stanów:

  • Nieśledzone — Git nigdy nie widział tego pliku; istnieje tylko na dysku.
  • Śledzone, niezmienione — plik dokładnie odpowiada ostatniej zatwierdzonej migawce.
  • Śledzone, zmodyfikowane — plik różni się od ostatniej zatwierdzonej migawki, ale nie został dodany do indeksu.
  • Śledzone, usunięte — plik został usunięty z dysku, ale usunięcie nie zostało dodane do indeksu.

Istotna subtelność, która myli wielu programistów: katalog roboczy nie jest prostą kopią repozytorium. Git rekonstruuje go, odczytując obiekty drzewa i dekompresując obiekty blob. Jeśli .git/ jest nienaruszony, zawsze możesz odtworzyć katalog roboczy od zera — odwrotna sytuacja nie jest prawdą.

Sparse Checkout dla dużych monorepo

W repozytoriach z dziesiątkami tysięcy plików (typowych w architekturach monorepo) możesz ograniczyć, które ścieżki Git materializuje w katalogu roboczym:

git sparse-checkout init --cone
git sparse-checkout set services/api services/auth

Jest to nieocenione na VPS z ograniczonym I/O dysku, ponieważ Git pomija dekompresję blobów dla ścieżek spoza stożka.

Obszar tymczasowy (indeks)

Obszar tymczasowy, wewnętrznie nazywany indeksem, to plik binarny zlokalizowany pod .git/index. Działa jako proponowany następny commit — zmienna migawka znajdująca się między katalogiem roboczym a stałym magazynem obiektów.

git add <file>          # Stage a specific file
git add -p              # Interactively stage hunks within a file
git add -u              # Stage all tracked modifications and deletions
git status              # Compare working directory and index against HEAD
git diff --cached       # Show diff between index and HEAD

Dlaczego indeks istnieje

Indeks rozwiązuje problem, który prostsze narzędzia VCS ignorują: częściowe commity. Możesz mieć zmodyfikowane pięć plików, ale chcieć umieścić w następnym commicie tylko trzy z nich. Indeks pozwala skomponować dokładnie taką migawkę, jaką zamierzasz zapisać, niezależnie od tego, co masz otwarte w edytorze.

Przypadek brzegowy — uszkodzenie indeksu: Jeśli awaria systemu przerwie git add, plik indeksu może ulec uszkodzeniu. Objawami są zawieszanie się git status lub wyświetlanie dziwnych wyników. Odzyskiwanie:

rm .git/index
git reset

Git odbudowuje indeks z HEAD bez dotykania katalogu roboczego.

Indeks jako rejestr konfliktów scalania

Podczas konfliktu scalania indeks przechowuje jednocześnie trzy wersje każdego pliku z konfliktem (etapy 1, 2 i 3 — baza, nasza wersja, ich wersja). Dlatego git diff --cached nie pokazuje nic użytecznego w trakcie konfliktu; potrzebujesz git diff --cc lub narzędzia do scalania, aby sprawdzić wszystkie trzy etapy.

Katalog .git/: anatomia magazynu obiektów

Katalog .git/ jest repozytorium. Wszystko inne — katalog roboczy, zdalne klony — jest z niego pochodne. Usunięcie .git/ zamienia repozytorium w zwykły katalog bez historii.

.git/
├── HEAD
├── config
├── description
├── index
├── COMMIT_EDITMSG
├── hooks/
├── info/
├── logs/
│   ├── HEAD
│   └── refs/
├── objects/
│   ├── info/
│   └── pack/
└── refs/
    ├── heads/
    ├── remotes/
    └── tags/

HEAD to zwykły plik tekstowy zawierający albo symboliczne odwołanie (wskazujące na gałąź), albo surowy skrót SHA-1 (stan odłączonego HEAD).

cat .git/HEAD
# ref: refs/heads/main        <-- on a branch
# a3f1c9d...                  <-- detached HEAD

Odłączony HEAD nie jest stanem błędu — jest zamierzony, gdy sprawdzasz tag lub konkretny commit w celu inspekcji. Niebezpieczeństwo polega na tworzeniu commitów w odłączonym HEAD: te commity są osiągalne tylko przez reflog, dopóki nie przypiszesz ich do gałęzi.

git checkout -b rescue-branch   # Attach detached commits to a new branch

config

Lokalny plik konfiguracyjny repozytorium. Nadpisuje ustawienia globalne (~/.gitconfig) i systemowe (/etc/gitconfig). Typowe wpisy:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
[remote "origin"]
    url = git@github.com:user/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

Na samodzielnie hostowanym serwerze będziesz często edytować ten plik bezpośrednio podczas rotacji zdalnych URL-i lub konfigurowania uploadpack.allowReachableSHA1InWant dla częściowych klonów.

refs/

Katalog refs/ zawiera zwykłe pliki tekstowe, z których każdy przechowuje pojedynczy skrót SHA-1. Są to nazwane wskaźniki, które umożliwiają nawigację po DAG Git.

Typ refŚcieżkaOpis
Lokalna gałąźrefs/heads/<name>Wskazuje na końcowy commit gałęzi
Gałąź śledząca zdalne repozytoriumrefs/remotes/<remote>/<name>Lokalna kopia końca gałęzi zdalnej
Lekki tagrefs/tags/<name>Wskazuje bezpośrednio na obiekt commit
Opatrzony adnotacją tagrefs/tags/<name>Wskazuje na obiekt tagu, który wskazuje na commit
Schowekrefs/stashWskazuje na commit schowka

Dla wydajności Git pakuje referencje do .git/packed-refs, gdy repozytorium zgromadzi ich wiele. Zawsze sprawdzaj oba miejsca podczas tworzenia skryptów operujących na referencjach.

Obiekty Git: niezmienne jądro

Wszystko przechowywane w .git/objects/ jest adresowane treścią: nazwa pliku to skrót SHA-1 (lub SHA-256 w nowszych wersjach Git) zawartości obiektu. Sprawia to, że Git jest z natury odporny na manipulacje — zmiana dowolnego bajtu zmienia skrót, przerywając łańcuch.

Cztery typy obiektów

Typ obiektuCo przechowujeWskazuje na
BlobSurowa zawartość pliku (bez nazwy pliku, bez uprawnień)Nic
DrzewoLista zawartości katalogu: nazwy plików, uprawnienia, SHA blobów/drzewBloby i inne drzewa
CommitAutor, osoba zatwierdzająca, znacznik czasu, wiadomość, SHA(s) rodzicówJedno drzewo + zero lub więcej commitów nadrzędnych
TagTożsamość osoby tagującej, znacznik czasu, wiadomość, podpis GPGZazwyczaj commit

Bezpośrednia inspekcja obiektów

# Show the type of any object
git cat-file -t a3f1c9d

# Show the content of any object
git cat-file -p a3f1c9d

# Show the tree of the current HEAD commit
git ls-tree HEAD

# Show a specific blob's content
git show HEAD:src/main.py

Luźne obiekty a pliki pack

Początkowo każdy obiekt jest przechowywany jako pojedynczy skompresowany plik w .git/objects/<2-char-prefix>/<38-char-suffix>. Są to luźne obiekty. Z czasem Git uruchamia git gc (garbage collection), aby zebrać luźne obiekty w pliki pack (.git/objects/pack/*.pack) z odpowiadającym indeksem (.pack.idx).

Pliki pack używają kompresji delta — przechowując różnicę między podobnymi obiektami zamiast pełnych kopii. Repozytorium z tysiącami podobnych plików tekstowych może znacznie zmniejszyć rozmiar po spakowaniu. Na VPS z ograniczoną pojemnością NVMe uruchamianie git gc --aggressive na dużych repozytoriach przed archiwizacją jest standardową praktyką.

git count-objects -vH    # Show loose object count and disk usage
git gc --aggressive      # Repack aggressively (CPU-intensive)
git verify-pack -v .git/objects/pack/*.idx | sort -k3 -n | tail -20
# Find the 20 largest objects in the pack

Historia commitów: skierowany graf acykliczny

Każdy obiekt commit zawiera dokładnie jeden wskaźnik do obiektu drzewa (migawka katalogu głównego) i zero lub więcej wskaźników do commitów nadrzędnych. Tworzy to DAG, w którym:

  • Zero rodziców = początkowy commit (commit główny)
  • Jeden rodzic = normalny commit
  • Dwóch rodziców = commit scalający
  • Trzech lub więcej rodziców = scalanie ośmiornicze (rzadkie, używane do integrowania wielu gałęzi funkcji jednocześnie)
git log --oneline --graph --all    # Visualize the full DAG
git log --format="%H %P"           # Show each commit's SHA and parent SHA(s)

Niezmienność commitów i przepisywanie historii

Ponieważ SHA commita jest pochodną jego zawartości (w tym SHA rodziców), każde przepisanie tworzy nowy commit z nowym SHA. Operacje takie jak git rebase, git commit --amend i git filter-repo nie modyfikują historii — tworzą równoległą historię. Stare commity pozostają w magazynie obiektów do czasu garbage collection.

Dlatego wymuszanie przepisanej historii na współdzieloną gałąź jest destrukcyjne: lokalne gałęzie współpracowników nadal wskazują na stary łańcuch commitów.

Gałęzie: lekkie wskaźniki

Gałąź to nic więcej niż 41-bajtowy plik zawierający skrót SHA-1. Tworzenie gałęzi jest natychmiastowe niezależnie od rozmiaru repozytorium, ponieważ Git zapisuje tylko jeden mały plik.

git branch feature/auth           # Create branch at current HEAD
git checkout -b feature/auth      # Create and switch in one step
git switch -c feature/auth        # Modern equivalent (Git 2.23+)
git branch -d feature/auth        # Delete (safe: refuses if unmerged)
git branch -D feature/auth        # Delete (force: regardless of merge status)

Wewnętrzna struktura gałęzi

cat .git/refs/heads/main
# a3f1c9d8e2b1f4c7d9e0a1b2c3d4e5f6a7b8c9d0

Gdy zatwierdzasz commit na gałęzi, Git zapisuje nowy SHA commita do tego pliku. To jest całość operacji „przesuwania wskaźnika gałęzi”.

Gałęzie śledzące i konfiguracja upstream

Relacja śledzenia informuje Git, którą zdalną gałąź lokalna gałąź powinna porównywać dla raportowania rozbieżności git status i zachowania git pull.

git branch --set-upstream-to=origin/main main
git branch -vv    # Show tracking relationships and ahead/behind counts

Tagi: trwałe znaczniki w historii

Tagi oznaczają konkretne commity jako istotne — zazwyczaj wydania oprogramowania. W przeciwieństwie do gałęzi, tagi nie są przesuwane przez nowe commity.

CechaLekki tagTag z adnotacją
PrzechowywaniePlik ref wskazujący na commitObiekt tagu w magazynie obiektów
MetadaneBrakNazwa osoby tagującej, email, data, wiadomość
Podpisywanie GPGNiemożliweObsługiwane przez git tag -s
Zalecane dla wydańNieTak
Transfer z git push --tagsTakTak
git tag v2.1.0                              # Lightweight tag at HEAD
git tag -a v2.1.0 -m "Release 2.1.0"       # Annotated tag
git tag -s v2.1.0 -m "Signed release"      # GPG-signed annotated tag
git push origin --tags                      # Push all tags to remote
git push origin v2.1.0                      # Push a specific tag

Krytyczna pułapka: git push domyślnie nie przesyła tagów. Zespoły często o tym zapominają i publikują informacje o wydaniu odwołujące się do tagu, który nie istnieje na zdalnym repozytorium.

Zdalne repozytoria: współpraca rozproszona

Zdalne repozytorium to nazwany URL przechowywany w .git/config. Gałęzie śledzące zdalne repozytoria (w refs/remotes/) to lokalne migawki tylko do odczytu gałęzi zdalnych, aktualizowane tylko wtedy, gdy jawnie pobierasz dane.

git remote add origin git@github.com:user/repo.git
git remote -v                          # List remotes with URLs
git remote set-url origin <new-url>    # Change a remote URL
git fetch origin                       # Update remote-tracking branches
git fetch --prune                      # Remove stale remote-tracking branches
git push origin main                   # Push local main to remote
git push -u origin feature/auth        # Push and set upstream tracking

Wiele zdalnych repozytoriów

Pojedyncze repozytorium może śledzić wiele zdalnych repozytoriów — typowe przy utrzymywaniu forka obok repozytorium upstream:

git remote add upstream git@github.com:original/repo.git
git fetch upstream
git merge upstream/main

Gdy samodzielnie hostujesz czyste repozytoria na serwerze dedykowanym dla swojego zespołu, każdy programista dodaje serwer jako zdalne repozytorium i używa uwierzytelniania kluczem SSH do dostępu push.

Hooki: automatyczne egzekwowanie przy każdym zdarzeniu Git

Hooki to wykonywalne skrypty w .git/hooks/. Git wywołuje je w określonych punktach przepływu pracy. Nie są transferowane przez git clone ani git push — każdy programista (lub serwer) musi je zainstalować niezależnie. Jest to częste źródło nieporozumień w środowiskach zespołowych.

Hooki po stronie klienta

HookWyzwalaczTypowe zastosowanie
pre-commitPrzed monitem o wiadomość commitaLinting, skanowanie sekretów, uruchamianie testów
prepare-commit-msgPo utworzeniu domyślnej wiadomościWstrzyknięcie nazwy gałęzi do wiadomości
commit-msgPo napisaniu wiadomości przez użytkownikaWymuszanie formatu conventional commit
post-commitPo zapisaniu commitaLokalne powiadomienia
pre-pushPrzed wykonaniem git pushUruchomienie pełnego zestawu testów
pre-rebasePrzed rozpoczęciem rebaseZapobieganie rebase’owaniu opublikowanych gałęzi

Hooki po stronie serwera

HookWyzwalaczTypowe zastosowanie
pre-receivePrzed aktualizacją referencjiWymuszanie ochrony gałęzi, odrzucanie force-push
updatePer-ref podczas odbieraniaEgzekwowanie polityki per-gałąź
post-receivePo aktualizacji wszystkich referencjiWyzwalanie CI/CD, wysyłanie powiadomień

Przykład: hook pre-commit do wykrywania sekretów

#!/usr/bin/env bash
# .git/hooks/pre-commit

if git diff --cached --name-only | xargs grep -lE '(AKIA|passwords*=|api_keys*=)' 2>/dev/null; then
    echo "ERROR: Potential secret detected in staged files. Commit aborted."
    exit 1
fi
exit 0

Nadaj mu uprawnienia do wykonania:

chmod +x .git/hooks/pre-commit

Do dystrybucji hooków w całym zespole użyj narzędzia takiego jak Husky (projekty Node.js) lub przechowuj hooki w katalogu hooks/ w głównym katalogu repozytorium i twórz do nich dowiązania symboliczne podczas konfiguracji projektu.

Reflog: siatka bezpieczeństwa

Reflog rejestruje każde przesunięcie HEAD i wskaźników gałęzi, w tym operacje, które pozornie niszczą historię (twarde resety, rebase’y, zmienione commity). Jest przechowywany w .git/logs/.

git reflog                          # Show HEAD movement history
git reflog show main                # Show movement history for a specific branch
git checkout HEAD@{3}               # Check out the state HEAD was in 3 moves ago
git branch recovered HEAD@{5}       # Recover commits by branching from a reflog entry

Wpisy reflogu wygasają domyślnie po 90 dniach (gc.reflogExpire). Na serwerze produkcyjnym rozważ wydłużenie tego okresu:

git config gc.reflogExpire 180
git config gc.reflogExpireUnreachable 30

Czyste repozytoria: hosting po stronie serwera

Czyste repozytorium nie ma katalogu roboczego. Zawiera tylko zawartość .git/ na poziomie głównym. Czyste repozytoria to właściwy format dla scentralizowanego hostingu — akceptują push bez komplikacji związanych z wyewidencjonowaną gałęzią.

git init --bare /srv/repos/myproject.git

Gdy wysyłasz dane do GitHub, GitLab lub samodzielnie hostowanego serwera Git, wysyłasz je do czystego repozytorium. Jeśli hostujesz własny serwer Git na VPS z cPanel lub zwykłym Linux VPS, czyste repozytoria w /srv/repos/ z dostępem SSH to standardowa architektura.

Inicjalizacja współdzielonego czystego repozytorium

# On the server
git init --bare --shared=group /srv/repos/project.git
chown -R git:developers /srv/repos/project.git

# On a developer's machine
git remote add origin git@yourserver.com:/srv/repos/project.git
git push -u origin main

Przechowywanie obiektów Git: rozmiar, integralność i konserwacja

Sprawdzanie kondycji repozytorium

git fsck --full          # Verify object integrity (finds dangling and corrupt objects)
git fsck --lost-found    # Write dangling objects to .git/lost-found/

Znajdowanie i usuwanie dużych obiektów

Duże pliki binarne przypadkowo zatwierdzone są częstą przyczyną rozdętych repozytoriów. Zidentyfikuj je przed użyciem git filter-repo do ich usunięcia:

# Find the 10 largest objects by compressed size
git verify-pack -v .git/objects/pack/*.idx 
  | sort -k3 -rn 
  | head -10 
  | awk '{print $1}' 
  | xargs -I{} git cat-file -p {}
# Remove a file from all history (requires git-filter-repo)
git filter-repo --path path/to/large-file.bin --invert-paths

Po filtrowaniu wszyscy współpracownicy muszą ponownie sklonować repozytorium — ich lokalne repozytoria odwołują się do skrótów SHA, które nie istnieją już w przepisanej historii.

Porównanie: kluczowe koncepcje repozytorium Git

KoncepcjaTypZmiennyPrzechowywany wTransferowany przez push/fetch
BlobObiektNie.git/objects/Tak (gdy osiągalny)
DrzewoObiektNie.git/objects/Tak (gdy osiągalny)
CommitObiektNie.git/objects/Tak (gdy osiągalny)
Tag z adnotacjąObiektNie.git/objects/Tylko z --tags
GałąźRefTak.git/refs/heads/Tak
Gałąź śledząca zdalne repozytoriumRefTak (przy fetch).git/refs/remotes/Nie (lokalna kopia)
Lekki tagRefNie.git/refs/tags/Tylko z --tags
HEADSymref/skrótTak.git/HEADNie
IndeksPlik binarnyTak.git/indexNie
HookiSkryptyTak.git/hooks/Nie
ReflogDziennikTak (automatycznie wygasa).git/logs/Nie

Praktyczna macierz decyzyjna i kluczowe wnioski

Użyj tej listy kontrolnej podczas konfigurowania lub audytowania repozytorium Git w swojej infrastrukturze:

Inicjalizacja repozytorium

  • Używaj git init --bare --shared=group dla każdego repozytorium, które będzie odbierać push od wielu użytkowników.
  • Przechowuj czyste repozytoria poza katalogami dostępnymi przez sieć (nigdy w /var/www/).

Kondycja magazynu obiektów

  • Uruchamiaj git fsck --full po każdym incydencie związanym z przechowywaniem lub błędzie systemu plików.
  • Planuj git gc okresowo na długo używanych repozytoriach; automatyzuj to przez cron na swoim serwerze.
  • Monitoruj rozmiar pliku pack za pomocą git count-objects -vH; sprawdzaj, jeśli liczba luźnych obiektów przekracza 1 000.

Higiena gałęzi i referencji

  • Usuwaj scalone gałęzie niezwłocznie; nieaktualne referencje gromadzą się i spowalniają operacje git fetch --prune.
  • Używaj git fetch --prune w pipeline’ach CI, aby unikać działania na usuniętych gałęziach zdalnych.

Wdrażanie hooków

  • Nigdy nie polegaj na .git/hooks/ dla polityki obowiązującej cały zespół — hooki nie są klonowane. Zamiast tego używaj hooków pre-receive po stronie serwera lub bramki CI.
  • Audytuj hooki po stronie serwera po każdej aktualizacji serwera Git; ścieżki interpreterów hooków mogą się zmieniać.

Bezpieczeństwo na samodzielnie hostowanych serwerach

  • Ogranicz dostęp SSH do użytkownika git za pomocą wymuszonych poleceń (command= w authorized_keys).
  • Używaj git-shell jako powłoki logowania dla użytkownika git, aby zapobiec wykonywaniu dowolnych poleceń.
  • Połącz swój serwer repozytorium z ważnym certyfikatem SSL, jeśli udostępniasz jakikolwiek interfejs webowy (Gitea, GitLab, cgit).

Przepisywanie historii

  • Nigdy nie przepisuj historii na gałęziach współdzielonych z innymi bez skoordynowanego planu migracji.
  • Po git filter-repo wszyscy współpracownicy muszą ponownie sklonować repozytorium; natychmiast zaktualizuj zdalne URL-e CI/CD.

Odzyskiwanie po awarii

  • Wydłuż czas wygasania reflogu na serwerach produkcyjnych (gc.reflogExpire = 180).
  • Utrzymuj dodatkowy czysty klon na osobnym hoście jako kopię zapasową; prosty git fetch z głównego serwera jest wystarczający.

FAQ

Jaka jest różnica między czystym a nieczystym repozytorium Git?

Nieczyste repozytorium ma katalog roboczy, w którym pliki są wyewidencjonowane, oraz podkatalog .git/ zawierający magazyn obiektów. Czyste repozytorium zawiera tylko magazyn obiektów w swoim katalogu głównym (bez katalogu roboczego) i jest właściwym formatem dla współdzielonego serwera odbierającego push.

Czy mogę odzyskać commity po uruchomieniu git reset --hard?

Tak, o ile commity nie zostały poddane garbage collection. Uruchom git reflog, aby znaleźć SHA commita, który chcesz odzyskać, a następnie git checkout -b recovery-branch <SHA>, aby przypisać go do nowej gałęzi. Wpisy reflogu są domyślnie przechowywane przez 90 dni.

Dlaczego git push nie transferuje moich tagów?

Z założenia git push transferuje tylko commity osiągalne z referencji, które jawnie wysyłasz. Tagi to osobne referencje i muszą być wysyłane za pomocą git push origin --tags (wszystkie tagi) lub git push origin <tagname> (konkretny tag).

Co dzieje się z indeksem podczas konfliktu scalania?

Indeks przechowuje jednocześnie wszystkie trzy wersje każdego pliku z konfliktem: etap 1 (wspólny przodek/baza), etap 2 (twoja wersja) i etap 3 (ich wersja). Normalny git add zapisuje tylko etap 0 (rozwiązany). Dopóki wszystkie konflikty nie zostaną rozwiązane i dodane do indeksu, git commit odmówi kontynuowania.

Czym różnią się hooki Git po stronie klienta od tych po stronie serwera?

Hooki po stronie klienta działają na maszynie programisty i nie są centralnie egzekwowane — każdy programista może je ominąć, usuwając plik hooka. Hooki po stronie serwera (pre-receive, update, post-receive) działają na serwerze hostingowym i nie mogą być omijane przez klienta, co czyni je właściwym punktem egzekwowania polityk ochrony gałęzi, wymagań dotyczących przeglądu kodu i wyzwalaczy CI/CD.

Bezpieczeństwo Hosting LiteSpeed Serwery Wirtualne
Administracja Bezpieczeństwo Dedykowane serwery
Linux