JZ Handbook v2.0
Výukový materiál · Git · Cloudflare Workers
🌿 Aroma 🍕 Pizza 🛠️ Toolkit 🧠 Bias 🦒

Git — jak to funguje
od základů

Výukový materiál pro technicky zdatného začátečníka. Od instalace přes interní model až po práci v GUI a řešení problémů.

Git 2.x Windows · macOS · Linux VS Code · CLI

§ 01 Instalace Gitu

Git je samostatný nástroj — není součástí VS Code ani jiného editoru, musí se nainstalovat zvlášť. Po instalaci ho používají všechny GUI klienty i terminál.

Doporučeno: Git for Windows — instaluje Git, Git Bash (terminál), Git Credential Manager (bezpečné ukládání hesel) a volitelně GUI nástroj.

Možnost 1 — winget (Windows 10/11, doporučeno)
# Spusťte PowerShell nebo CMD jako běžný uživatel
winget install --id Git.Git -e --source winget

# Po instalaci ověřte — zavřete a znovu otevřete terminál!
git --version
git version 2.47.1.windows.1
Možnost 2 — instalátor (.exe)
# Stáhněte instalátor z git-scm.com/download/win
# Při instalaci doporučená nastavení:
  Default editor:       Visual Studio Code (nebo Notepad++)
  Initial branch name:  main  ← ZMĚŇTE z "master"
  PATH environment:     Git from command line (doporučeno)
  Line ending:          Checkout Windows / Commit Unix (výchozí)
  Credential helper:    Git Credential Manager
Co je Git Bash? Git for Windows přináší Git Bash — emulátor linuxového terminálu pro Windows. Fungují v něm všechny příkazy z tohoto materiálu. Alternativně používejte PowerShell nebo Windows Terminal — Git tam funguje stejně.

Doporučeno: Homebrew. macOS sice Git obsahuje, ale jeho verze je zastaralá (Apple ji neaktualizuje). Homebrew nainstaluje aktuální verzi.

Instalace přes Homebrew (doporučeno)
# Nejdřív nainstalujte Homebrew (pokud ho nemáte)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Pak nainstalujte Git
brew install git

# Ověření — musí to zobrazit Homebrew cestu, ne /usr/bin/git
which git
/opt/homebrew/bin/git   ← správně (Apple Silicon)
git --version
git version 2.47.1
Alternativa: Xcode Command Line Tools
# Nainstaluje Git spolu s vývojářskými nástroji Apple
xcode-select --install
# Nevýhoda: starší verze Gitu, aktualizace jen s macOS updatem
Git Credential Manager na macOS brew install --cask git-credential-manager — bezpečné ukládání přihlašovacích údajů do systémové klíčenky (Keychain). Bez něj budete zadávat heslo při každém push/pull.

Na Linuxu je Git dostupný přímo v balíčkovacím systému distribuce.

Debian / Ubuntu / Mint
sudo apt update
sudo apt install git
# Nebo kompletní balík s extra nástroji:
sudo apt install git-all
Fedora / RHEL / CentOS
sudo dnf install git
Arch Linux
sudo pacman -S git
Ověření na všech distribucích
git --version
git version 2.43.0

§ 02 Výběr Git klienta

Git samotný je jen nástroj příkazového řádku. Klient je aplikace, která ho obaluje grafickým rozhraním. Použití klienta není povinné — vše jde dělat v terminálu — ale pro denní práci s kódem kombinace editoru a terminálu funguje nejlépe.

KlientTypOSPro kohoCena
Terminál (Git Bash, PowerShell, zsh) CLI Všechny Přesná kontrola, scripty, CI/CD — základ, který by měl znát každý zdarma
VS Code (vestavěný + rozšíření) GUI v editoru Všechny Vývojáři, kteří chtějí Git přímo v editoru — doporučeno pro tento materiál zdarma
GitHub Desktop GUI standalone Win, macOS Absolutní začátečníci na GitHubu, velmi jednoduchý workflow zdarma
GitKraken GUI standalone Všechny Vizualizace složitých branch grafů, týmová spolupráce freemium
SourceTree GUI standalone Win, macOS Uživatelé Atlassian stacku (Jira, Bitbucket) zdarma
TortoiseGit Shell extension Windows Uživatelé Průzkumníka Windows, zvyklí na TortoiseSVN zdarma
IntelliJ / Rider / WebStorm GUI v editoru Všechny Uživatelé JetBrains IDE — velmi propracovaná integrace placené
Doporučení pro tento materiál Používejte VS Code pro denní práci (staging, commit, zobrazení diff, řešení konfliktů) a terminál pro složitější operace (rebase, reset, reflog). Sekce D (§11–§14) pokrývá VS Code detailně.

§ 03 První nastavení po instalaci

Po instalaci Gitu je potřeba nastavit identitu — Git ji připisuje každému commitu. Toto nastavení je globální (platí pro všechny projekty na počítači).

Povinná prvotní konfigurace (všechny OS)
# Vaše jméno — zobrazí se u každého commitu
git config --global user.name "Jan Novák"

# Váš e-mail — měl by odpovídat účtu na GitHubu/GitLabu
git config --global user.email "jan@example.com"

# Výchozí název hlavní větve (moderní standard)
git config --global init.defaultBranch main

# Výchozí editor pro zprávy commitů (vyberte jeden)
git config --global core.editor "code --wait"    ← VS Code
git config --global core.editor "notepad"           ← Poznámkový blok
git config --global core.editor "nano"              ← nano (macOS/Linux)

# Ověření — zobrazí všechna nastavení
git config --list --global
user.name=Jan Novák
user.email=jan@example.com
init.defaultbranch=main
core.editor=code --wait
Kde se ukládá konfigurace?

--global nastavení se ukládají do souboru ~/.gitconfig (macOS/Linux) nebo C:\Users\VašeJméno\.gitconfig (Windows). Lze ho otevřít a editovat přímo jako textový soubor.

Nastavení bez --global platí jen pro aktuální repozitář a ukládají se do .git/config ve složce projektu.

Nastavení přihlašování k GitHubu / GitLabu

Pro push a pull potřebujete způsob autentizace. Doporučujeme SSH klíč — heslo zadáte jen jednou (při vytvoření klíče) a dál vše funguje automaticky.

Generování SSH klíče a připojení k GitHubu
# 1. Vygenerujte SSH klíč (funguje na Windows i macOS i Linux)
ssh-keygen -t ed25519 -C "jan@example.com"
# Potvrďte výchozí cestu (Enter), nastavte heslo (nebo nechte prázdné)

# 2. Zkopírujte veřejný klíč
# Windows:
cat ~/.ssh/id_ed25519.pub ← zkopírujte celý výstup
# macOS:
pbcopy < ~/.ssh/id_ed25519.pub  ← uloží do schránky

# 3. Přidejte klíč na GitHub:
#    github.com → Settings → SSH and GPG keys → New SSH key
#    Vložte zkopírovaný klíč a uložte

# 4. Ověřte připojení
ssh -T git@github.com
Hi jan! You've successfully authenticated.
HTTPS s Personal Access Tokenem
# GitHub již nepřijímá heslo — potřebujete Personal Access Token (PAT)
# github.com → Settings → Developer settings → Personal access tokens → Fine-grained
# Nastavte oprávnění: Contents (Read and write), Metadata (Read)

# Git Credential Manager (součást Git for Windows) uloží token automaticky
# Při prvním push/pull se zobrazí přihlašovací okno — vložte token jako heslo

# Manuální uložení tokenu (macOS/Linux bez GCM):
git config --global credential.helper store
# Token se uloží při příštím push/pull (pozor: ukládá nešifrovaně)

§ 04 Jak číst příkazy v tomto materiálu

Legenda barev
git commit -m "zpráva commitu"
# Toto je komentář — vysvětluje co příkaz dělá. Do terminálu ho nepište.
On branch main   ← toto Git vypsal jako odpověď
CONFLICT: ...    ← varování nebo chybová zpráva
   ← kurzíva = naše vysvětlivka, ne součást příkazu
ZkratkaCo znamená v praxi
HEAD~1„o jeden commit zpět" — HEAD~3 = o tři zpět. HEAD je vždy aktuální pozice.
originVýchozí název vzdáleného repozitáře (GitHub/GitLab). Nastavuje se automaticky při git clone.
origin/mainLokální záložka stavu větve main na serveru — aktualizuje se jen při git fetch.
upstreamVazba mezi vaší lokální větví a větví na serveru. Po nastavení (git push -u origin main) stačí psát jen git push.
a1b2c3dZkrácený hash commitu (7 znaků). Git si domyslí zbytek 40znakového hashe.

§ 05 Jak Git interně ukládá data

Git ukládá vše do skryté složky .git/ ve vašem projektu jako čtyři typy objektů. Každý objekt je jednoznačně identifikován kryptografickým hashem svého obsahu.

TypCo obsahujePříklad
blobObsah jednoho souboru — jen data, bez názvu a cestyObsah README.md
treeAdresář: seznam názvů + hash blobu nebo podadresářeSložka src/
commitSnímek projektu: hash tree, hash předchozího commitu, autor, čas, zprávaKaždý váš git commit
tagNepohyblivý, pojmenovaný ukazatel na commitv1.0.0
Proč blob neobsahuje název souboru? Blob ukládá jen obsah. Dva soubory se stejným obsahem kdekoliv v projektu sdílí jediný blob — žádné kopírování, žádné plýtvání místem. Název souboru ukládá nadřazený objekt tree.
Obsah commit objektu — git cat-file -p HEAD
tree   4b825dc642cb6eb9a060e54bf8d69288fbee4904  ← snímek souborů
parent f3a9b1c8d27e44f1a5c3b9e0d7f2a6c4b8e1d5f9  ← předchozí commit
author Jan Novák <jan@example.com> 1706000000 +0100
committer Jan Novák <jan@example.com> 1706000000 +0100

feat: přidán modul pro autentizaci
Co najdete ve složce .git/
.git/
├── objects/         ← všechny objekty (blob/tree/commit/tag)
│   ├── a1/b2c3d4...  ← první 2 znaky hashe = složka
│   └── pack/         ← zabalené objekty po automatické optimalizaci
├── refs/heads/main  ← soubor s jedním řádkem: hash posledního commitu větve
├── refs/remotes/    ← stav větví na serveru (aktualizuje se při fetch)
├── HEAD              ← "ref: refs/heads/main" = kde se právě nacházíte
├── index             ← staging area — seznam souborů připravených ke commitu
└── config            ← nastavení tohoto repozitáře

§ 06 Tři oblasti a klíčové pojmy

Soubor může existovat ve třech různých „stavech" zároveň. Toto je nejdůležitější věc k pochopení — zdroj většiny zmatení u začátečníků.

Cesta změny — od úpravy souboru až na server
Working Directory
soubory na disku,
jak je vidíte v editoru
git add
Index / Staging
„fronta" připravených
změn k zapsání
git commit
Lokální repozitář
trvalá historie
ve složce .git/
git push
Remote repozitář
GitHub / GitLab
sdíleno s týmem
TermínVysvětleníAnalogie
Working DirectorySoubory na disku — jak je vidíte v editoru. Git je sleduje, ale zatím nic nezapsal.Rozepsaný dokument
Index / StagingPřechodná oblast pro sestavení commitu. Přidáváte sem pomocí git add. Umožňuje zařadit jen část změn.Krabice připravená k odeslání
CommitTrvalý, neměnný záznam stavu souborů s unikátním hashem a zprávou.Odeslaná zásilka s razítkem
Branch (větev)Pojmenovaný ukazatel na commit. Po každém commitu se automaticky posune vpřed.Záložka v knize
HEADSpeciální reference říkající „kde teď jsem". Ukazuje na aktuální větev.„Jste zde" na mapě
RemoteVzdálený repozitář (GitHub…). Lokálně vidíte jeho stav jako origin/main — aktualizuje se jen při git fetch.Sdílená schránka pro tým
TagNepohyblivý štítek na commitu — neposouvá se při nových commitech. Pro označení verzí.Trvalá etiketa

§ 07 Commit workflow

Inicializace nového repozitáře
mkdir muj-projekt && cd muj-projekt
git init
Initialized empty Git repository in /muj-projekt/.git/

echo "# Můj projekt" > README.md
git add README.md
git commit -m "chore: initial commit"
[main (root-commit) a1b2c3d] chore: initial commit
Klonování existujícího repozitáře
# Stáhne kompletní historii a nastaví "origin" automaticky
git clone https://github.com/org/repo.git

# SSH varianta (po nastavení SSH klíče, viz §03)
git clone git@github.com:org/repo.git

git remote -v
origin  git@github.com:org/repo.git (fetch)
origin  git@github.com:org/repo.git (push)
Denní commit cyklus
# 1. Zjistěte stav
git status
  modified:   src/auth.py   ← upraveno, není ve staging
  Untracked:  docs/api.md   ← nový soubor, Git ho nezná

# 2. Přidejte do staging
git add src/auth.py docs/api.md

# 3. Zkontrolujte co půjde do commitu
git diff --staged

# 4. Zapište commit
git commit -m "feat(auth): přidána podpora JWT tokenů"

# 5. Odešlete na server
git push

§ 08 Větvení

Branch je jen soubor s hashem commitu — vytvoření trvá milisekundy. Pro každou novou funkci nebo opravu si vytvořte samostatnou větev.

Práce s větvemi
# Vytvořte novou větev a přepněte se na ni
git switch -c feature/prihlaseni

# Seznam větví (* = aktuální)
git branch -a
* feature/prihlaseni
  main
  remotes/origin/main

# Přepnutí zpět
git switch main

# Smazání po mergi (Git hlídá, aby byla větev sloučena)
git branch -d feature/prihlaseni
Detached HEAD Pokud se přepnete přímo na hash commitu (git checkout a1b2c3d), HEAD přestane ukazovat na větev. Nové commity v tomto stavu nemají větev — Git je po čase smaže. Okamžitá záchrana: git switch -c nova-vetev.

§ 09 Merge & Rebase

Aspektgit mergegit rebase
Co uděláVytvoří nový „merge commit" se dvěma rodičiPřepíše commity vaší větve od vrcholu jiné větve
Výsledná historieZachová skutečný průběh vývojeLineární — jako by větvení nebylo
Bezpečné na sdílenou větev?✓ Ano✗ Ne — přepíše hashe
Kdy použítIntegrace feature do mainČištění feature větve před PR

Nejjednodušší případ: main se od odbočení nezměnil. Git jen posune ukazatel vpřed — žádný merge commit.

Fast-forward merge
git switch main
git merge feature/prihlaseni
Fast-forward   ← žádný merge commit, jen posunutí ukazatele

# Pokud chcete merge commit i přesto (pro přehlednost v historii):
git merge --no-ff feature/prihlaseni

Obě větve měly vlastní commity. Git najde společného předka, porovná obě větve a vytvoří merge commit.

3-way merge
git switch main
git merge feature/prihlaseni
Merge made by the 'ort' strategy.

# Výsledný graf:
*   e5f6a7b Merge branch 'feature/prihlaseni'
|\
| * d2e3f4a feat: JWT tokeny
* | f1g2h3i docs: README
|/
* b5c6d7e feat: auth module

Konflikt nastane, když obě větve upravily stejné řádky stejného souboru. Git se zastaví a čeká na vaše rozhodnutí.

1

Git ohlásí konflikt

Výstup při konfliktu
git merge feature/prihlaseni
CONFLICT (content): Merge conflict in src/config.py
Automatic merge failed; fix conflicts and then commit.

git status
Unmerged paths:
  both modified:   src/config.py   ← tento soubor má konflikt
2

Otevřete soubor — Git v něm označil obě verze

src/config.py — jak soubor vypadá po konfliktu
DEBUG = False
<<<<<<< HEAD
TIMEOUT = 30 # vaše verze (větev main)
═══════════════════════
TIMEOUT = 60 # příchozí verze (feature/prihlaseni)
>>>>>>> feature/prihlaseni
MAX_RETRIES = 3

Sekce od <<<<<<< HEAD po ═══ je vaše verze. Sekce od ═══ po >>>>>>> je příchozí verze.

3

Ručně upravte soubor — vyberte nebo zkombinujte obě verze

Smažte všechny markery (<<<<<<<, =======, >>>>>>>) a ponechte výsledný kód:

src/config.py — po vyřešení
DEBUG = False
TIMEOUT = 60 # přijato z feature větve
MAX_RETRIES = 3
4

Označte soubor jako vyřešený a dokončete commit

Dokončení merge
git add src/config.py       ← říká Gitu: „konflikt vyřešen"
git commit                   ← Git nabídne výchozí zprávu, potvrďte

# Chcete vše vrátit a začít merge znovu?
git merge --abort            ← vrátí stav přesně před merge
Tip: Merge Editor ve VS Code VS Code zobrazí konflikt graficky — tlačítka Accept Current, Accept Incoming, Accept Both. Viz §14 pro detailní postup.
Rebase feature větve na aktuální main
git switch feature/prihlaseni
git rebase main
Successfully rebased and updated refs/heads/feature/prihlaseni.

# Interaktivní — přepis posledních 3 commitů (squash, rename, drop…)
git rebase -i HEAD~3

# Pokud nastane konflikt:
git add soubor.py
git rebase --continue   ← nebo --abort pro zrušení celého rebase
Zlaté pravidlo rebase Rebase přepíše SHA hashe commitů. Nikdy nerebazujte větve sdílené s ostatními — main, develop ani jiné společné větve. Pouze vaše vlastní feature větve.

§ 10 Remote a sdílení s týmem

PříkazCo děláMění lokální větve?
git fetchStáhne nové commity ze serveru, aktualizuje origin/mainNe
git pullfetch + automatický merge do aktuální větveAno
git pushOdešle lokální commity na server
Push & Pull — praktické příklady
# První push větve — -u nastaví upstream (vazbu na server)
# Po nastavení stačí příště psát jen "git push"
git push -u origin feature/prihlaseni
Branch set up to track 'origin/feature/prihlaseni'.

# Bezpečné stažení: nejdřív fetch, pak se podívejte co přišlo
git fetch origin
git log main..origin/main --oneline  ← co přibylo na serveru
git merge origin/main

# Nebo zkratkou (= fetch + merge)
git pull origin main

# Vynucený push po rebase (jen pro VLASTNÍ větve)
# --force-with-lease selže, pokud někdo jiný mezitím pushnul — bezpečnější než --force
git push --force-with-lease origin feature/prihlaseni

§ 10b .gitignore — co nesledovat

Soubor .gitignore říká Gitu, které soubory a složky má ignorovat — neřadit je do staging ani do commitů. Typicky se jedná o sestavovací výstupy, dočasné soubory, citlivé informace a závislosti stažené ze správce balíčků.

Vzorový .gitignore

.gitignore — vzorový soubor pro obecný projekt
# OS
.DS_Store
Thumbs.db

# Logs
*.log
logs/

# Temp
tmp/
temp/
*.tmp

# IDE
.vscode/
.idea/
*.user

# Secrets
.env
*.key
*.pfx

# Build
bin/
obj/
dist/
build/

# Node
node_modules/

# Python
__pycache__/
*.pyc

# Misc
*.bak
*.swp
Kde soubor umístit? Do kořene repozitáře, vedle složky .git/. Pravidla platí rekurzivně pro všechny podsložky — pokud chcete omezit pravidlo jen na jednu složku, přidejte lomítko na začátek: /build/.

Cleanup — odebrání souborů, které Git už sleduje

Přidání pravidla do .gitignore nezastaví sledování souborů, které Git již zná. Nejprve je musíte odebrat z indexu příkazem git rm --cached.

Postup cleanup — odebrání sledovaných souborů z indexu
# 1. Přidejte (nebo doplňte) pravidlo do .gitignore
echo ".env" >> .gitignore

# 2. Odeberte konkrétní soubor z indexu (soubor na disku zůstane)
git rm --cached .env

# Alternativa: odebrání celé složky rekurzivně
git rm --cached -r node_modules/

# 3. Ověřte stav — soubor by měl zmizet ze sledovaných
git status
Changes to be committed:
  deleted:    .env   ← bude odstraněn z Gitu, ale fyzicky zůstane

# 4. Zacommitujte změnu
git commit -m "chore: remove .env from tracking, update .gitignore"

# Hromadný cleanup — přepsat celý index podle aktuálního .gitignore
# Pozor: dočasně odebere vše a znovu přidá jen neignorvané soubory
git rm --cached -r .
git add .
git commit -m "chore: apply .gitignore cleanup"
Pozor na historii! Soubory odstraněné z indexu zůstanou ve starších commitech viditelné. Pokud omylem commitnete citlivá data (hesla, klíče), nestačí je přidat do .gitignore — musíte přepsat historii (git filter-repo) a zneplatnit všechna kompromitovaná tajemství.

§ 11 Git ve VS Code — orientace v GUI

VS Code má Git integraci vestavěnou — nepotřebujete žádné rozšíření pro základní operace. Tato sekce popisuje, kde co najít.

Source Control panel (Ctrl+Shift+G)

muj-projekt — Visual Studio Code
🗂
🔍
🐛
🧩
Source Control ↻ ✓ …
A docs/api.md docs
M src/auth.py src
M README.md .
+
⎇ main
↑2 ↓0
0 1
Prvek UICo znamená
Staged ChangesSoubory přidané do staging (git add) — půjdou do příštího commitu
ChangesUpravené soubory, které ještě nejsou ve staging
A / M / D / UAdded / Modified / Deleted / Untracked — stav souboru
↑2 ↓0Stavový řádek: máte 2 lokální commity, které jste nepushnuli; 0 stažených ze serveru
⎇ mainAktuální větev — kliknutím ji změníte nebo vytvoříte novou
Pole pro zprávu commituSem napište zprávu a stiskněte Ctrl+Enter (nebo Cmd+Enter na macOS) pro commit
Ikona v paneluCommit tlačítko (alternativa k Ctrl+Enter)
Ikona v paneluRozbalovací menu — Push, Pull, Fetch, Branch, Stash a další

Zobrazení rozdílů (diff)

Klikněte na soubor ve Changes — VS Code otevře diff editor s původní verzí vlevo a upravenou vpravo. Kliknutím na soubor ve Staged Changes uvidíte, co přesně půjde do commitu (ekvivalent git diff --staged).

§ 12 GUI ↔ CLI — ekvivalenty operací

Každou operaci z terminálu lze provést i ve VS Code. Tabulka ukazuje obě cesty pro nejčastější úkony.

OperacePříkaz (terminál)VS Code GUI
Zobrazit stav git status Source Control panel — automaticky, vždy aktuální
Přidat soubor do staging git add soubor.py Klik na + vedle souboru ve Changes
Přidat vše do staging git add . Klik na + vedle nadpisu Changes
Odebrat ze staging git restore --staged soubor.py Klik na vedle souboru ve Staged Changes
Zahodit lokální změny git restore soubor.py Klik na (Discard Changes) vedle souboru
Zobrazit diff souboru git diff soubor.py Klik na soubor ve Changes
Commit git commit -m "zpráva" Napsat zprávu do pole → Ctrl+Enter
Push git push menu → Push nebo tlačítko Sync Changes (↑↓) ve stavovém řádku
Pull git pull menu → Pull
Fetch git fetch menu → Fetch
Vytvořit větev git switch -c nova-vetev Klik na název větve ve stavovém řádku → Create new branch…
Přepnout větev git switch jina-vetev Klik na název větve ve stavovém řádku → vyberte větev ze seznamu
Merge větve git merge feature/xyz menu → BranchMerge Branch…
Stash (odložit změny) git stash push -m "popis" menu → StashStash All Changes
Stash pop (obnovit) git stash pop menu → StashApply Latest Stash
Zobrazit historii git log --oneline --graph Rozšíření Git Graph (viz §13) — vestavěná integrace je omezená
Anotace řádků (blame) git blame soubor.py Rozšíření GitLens → inline anotace při najetí myší
Integrovaný terminál Pro operace, které v GUI nejsou — rebase, reset, reflog — otevřete terminál přímo ve VS Code: Ctrl+` (backtick). Pracujete ve stejné složce projektu, GUI a terminál se navzájem vidí a synchronizují.

§ 13 Doporučená rozšíření a jejich konfigurace

Instalace rozšíření: Ctrl+Shift+X → vyhledejte název → Install.

GitLens — inline anotace a rozšířená historie

eamodio.gitlens

Nejpopulárnější Git rozšíření pro VS Code. Zobrazuje inline anotace (kdo a kdy změnil řádek), procházení historie souboru, porovnávání větví a vizuální commit graph.

Klíčové funkce

  • Inline blame: při najetí na řádek vidíte autora, datum a zprávu commitu
  • File History: pravý klik na soubor → Open File History
  • Commit Graph: vizuální přehled větví (GitLens → Commit Graph)
  • Revision Navigation: tlačítka ← → pro procházení verzí souboru

Doporučená konfigurace (settings.json)

VS Code settings.json — GitLens
{
  "gitlens.currentLine.enabled": true,        ← blame na aktuálním řádku
  "gitlens.hovers.currentLine.over": "line",  ← detail při hoveru
  "gitlens.codeLens.enabled": false,          ← vypnout pokud ruší v kódu
  "gitlens.statusBar.enabled": true           ← stav v stavovém řádku
}
Git Graph — vizualizace commit grafu

mhutchie.git-graph

Zobrazí interaktivní commit graph přímo ve VS Code — větvení, merges, tagy. Spustíte přes menu → View Git Graph nebo příkazovou paletou (Ctrl+Shift+PGit Graph: View Git Graph).

Co v grafu lze dělat

  • Klik na commit — zobrazí detail a diff souborů
  • Pravý klik na commit — Checkout, Cherry Pick, Revert, Tag
  • Pravý klik na větev — Merge, Rebase, Delete
  • Filtrování podle větve nebo autora
Tip Git Graph je nejrychlejší způsob, jak pochopit stav repozitáře — otevřete ho vždy, když nevíte „kde teď jste".
Git History — procházení změn v souborech

donjayamanne.githistory

Doplňuje vestavěnou integraci o procházení historie konkrétního souboru nebo řádku. Pravý klik na soubor → Git: View File History.

  • Zobrazení všech commitů, které dotýkaly daného souboru
  • Porovnání libovolných dvou verzí souboru
  • Zobrazení commitu, který změnil konkrétní řádek
GitHub Pull Requests — PR přímo v editoru

github.vscode-pull-request-github

Pokud pracujete s GitHubem, toto rozšíření přináší Pull Request workflow přímo do VS Code: vytvoření PR, code review s komentáři inline, merge — vše bez otevírání prohlížeče.

Po instalaci: přihlaste se přes GitHub Account (ikona účtu v sidebar) a repozitář musí mít origin nastavený na GitHub.

Nastavení VS Code specifická pro Git

Doporučená settings.json pro Git workflow
{
  // Automatický fetch každých 3 minuty (zobrazí ↓ v stavovém řádku)
  "git.autofetch": true,
  "git.autofetchPeriod": 180,

  // Potvrzení před synchronizací (push + pull najednou)
  "git.confirmSync": true,

  // Automatický commit po stage (vypnuto — lepší mít kontrolu)
  "git.enableSmartCommit": false,

  // Zobrazit počet commitů čekajících na push v stavovém řádku
  "scm.countBadge": "all",

  // Výchozí větev pro nové repozitáře
  "git.defaultBranchName": "main",

  // Řádkové konce — důležité pro týmy s různými OS
  "files.eol": "\n"
}

§ 14 Řešení merge konfliktu ve VS Code

VS Code vs Git VS Code je jen grafické rozhraní nad Gitem. Konflikty detekuje a označuje Git — VS Code je pouze zobrazuje a usnadňuje výběr. Výsledek se vždy zapíše příkazem git commit.

VS Code (od verze 1.69) obsahuje Merge Editor — grafické rozhraní pro řešení konfliktů. Aktivuje se automaticky při otevření konfliktního souboru.

Jak Merge Editor vypadá

Merge Editor zobrazí tři panely vedle sebe:

PanelObsahOdpovídá
Incoming (vlevo)Verze přicházející z mergované větveSekce >>>>>>> v souboru
Current (vpravo)Vaše aktuální verze (větev, kam mergujete)Sekce <<<<<<< HEAD
Result (dole)Výsledný soubor — zde vidíte a editujete konečnou podobuCo bude zapsáno

Postup řešení konfliktu krok za krokem

1

Otevřete Merge Editor

VS Code zobrazí v horní části souboru banner s konfliktem. Klikněte na tlačítko Resolve in Merge Editor.

2

Pro každý konflikt vyberte akci

Nad každým konfliktem se zobrazí tlačítka — vyberte jedno:

TlačítkoCo udělá
Accept CurrentZachová vaši verzi (pravý panel)
Accept IncomingPřijme příchozí verzi (levý panel)
Accept BothVloží obě verze za sebou (nejdřív Current, pak Incoming)
(ruční editace)Klikněte přímo do panelu Result a upravte text libovolně
Pozor: Current/Incoming se liší podle operace Při merge: Current = HEAD vaší větve, Incoming = mergovaná větev.
Při rebase: Current = commit, který se přehrává (z vaší větve), Incoming = větev, na kterou rebazujete. Termíny jsou v rebase kontextu opačně intuitivní — ověřte si vždy v panelu Result.
3

Dokončete v panelu Result

Zkontrolujte panel Result — musí být syntakticky správný, bez zbylých markerů. Pak klikněte Complete Merge v pravém dolním rohu Merge Editoru.

4

Commitněte

VS Code automaticky přidá vyřešený soubor do staging. Napište zprávu do Source Control panelu a stiskněte Ctrl+Enter.

Tip: Zobrazení tří panelů vedle sebe Pokud preferujete místo Merge Editoru přímou editaci souboru, klikněte v banneru na Resolve in Editor. Uvidíte soubor s markery a kontextové akce (CodeLens) přímo nad každým konfliktem.

§ 15 Troubleshooting — časté problémy

💥 Potřebuji vrátit poslední commit (ale zachovat změny)
Tři varianty resetu
# Zruší commit, soubory zůstanou ve staging (připravené ke commitu)
git reset --soft HEAD~1

# Zruší commit, soubory zůstanou na disku ale ne ve staging
git reset HEAD~1

# Zruší commit A smaže i změny na disku (DESTRUKTIVNÍ — nelze vrátit)
git reset --hard HEAD~1
💥 Opravuji commit, který jsem právě zapsal
git commit --amend
# Přidejte zapomenuté soubory do staging, pak:
git commit --amend              ← přepíše poslední commit (nový hash)
git commit --amend -m "nová zpráva"  ← jen změna zprávy

# Pokud jste commit již pushnuli na VLASTNÍ feature větev:
git push --force-with-lease

# Pushnuto na sdílenou větev? Amend NEPROVÁDĚJTE.
# Místo toho vytvořte nový opravný commit:
git revert HEAD   ← nový commit, který předchozí bezpečně „odvolá"
💥 Omylem smazaná větev nebo ztracené commity

Git málokdy opravdu smaže data — jen je přestane referencovat. git reflog zaznamenává všechny pohyby HEAD za posledních 90 dní.

Záchrana přes reflog
git reflog
d2e3f4a HEAD@{0}: merge: Fast-forward
b5c6d7e HEAD@{1}: checkout: moving to main
c9d0e1f HEAD@{2}: commit: fix: login bug  ← tento commit hledáte

# Obnovte smazanou větev z konkrétního commitu:
git branch zachrana c9d0e1f

# Nebo se přepněte přímo:
git switch -c zachrana HEAD@{2}
💥 git push odmítnut — remote je napřed

Někdo jiný pushnul změny na server dříve než vy. Vaše větev a serverová větev se „rozcházejí".

Řešení odmítnutého push
! [rejected] main -> main (non-fast-forward)
hint: Updates were rejected because the remote contains work you do not have.

# Stáhněte a integrujte cizí změny, pak znovu pushnul:
git pull --rebase origin main
git push origin main
💥 Potřebuji dočasně odložit rozdělanou práci
git stash
# Uloží všechny neuložené změny do zásobníku (working dir + staging)
git stash push -m "WIP: přihlašovací formulář"

# Přepněte, udělejte jiný úkol, vraťte se…
git stash list
stash@{0}: On feature/prihlaseni: WIP: přihlašovací formulář

# Obnovte a smažte ze zásobníku
git stash pop
💥 Jsem uprostřed merge nebo rebase a chci to přerušit

Pokud jste spustili merge nebo rebase a situace je nepřehledná, můžete celou operaci zrušit a vrátit repozitář přesně do stavu před ní.

Přerušení merge nebo rebase
# Zrušit probíhající merge (včetně všech konfliktů)
git merge --abort

# Zrušit probíhající rebase
git rebase --abort

# Ověřte stav — mělo by hlásit čistý stav
git status
On branch main
nothing to commit, working tree clean
💥 Potřebuji přenést konkrétní commit z jiné větve
git cherry-pick
# Aplikuje konkrétní commit na aktuální větev (bez přepínání)
git cherry-pick c9d0e1f

# Více commitů najednou:
git cherry-pick c9d0e1f d2e3f4a

# Bez okamžitého commitu (pro ruční úpravu před zápisem):
git cherry-pick -n c9d0e1f

§ 17 git-crypt — šifrování souborů v repozitáři

git-crypt umožňuje transparentně šifrovat vybrané soubory přímo v repozitáři pomocí GPG nebo sdíleného symetrického klíče. Ostatní soubory zůstávají nešifrované — spolupráce na nich funguje normálně.

Jak to funguje

Šifrování probíhá přes Git smudge/clean filtry: při git add se soubor zašifruje, při git checkout automaticky dešifruje. Pro kohokoli bez klíče vypadají chráněné soubory v repozitáři jako binární šum.

Instalace

Instalace git-crypt
# macOS (Homebrew)
brew install git-crypt

# Debian / Ubuntu
sudo apt install git-crypt

# Windows — přes WSL nebo Scoop
scoop install git-crypt

Inicializace a konfigurace .gitattributes

Inicializace a nastavení šifrovaných souborů
# 1. Inicializujte git-crypt v repozitáři (vytvoří symetrický klíč)
git-crypt init

# 2. Nastavte, které soubory se mají šifrovat — editujte .gitattributes
#    Přidejte řádky ve formátu: <vzor> filter=git-crypt diff=git-crypt

.gitattributes !filter !diff
secretfile filter=git-crypt diff=git-crypt
*.key filter=git-crypt diff=git-crypt
secrets/** filter=git-crypt diff=git-crypt

# 3. Zacommitujte .gitattributes (samotná pravidla nejsou tajná)
git add .gitattributes
git commit -m "chore: add git-crypt config"

Správa klíčů — symetrický klíč (jednoduchý přístup)

Export a import symetrického klíče
# Export klíče do souboru — tento soubor NIKDY necommitujte!
git-crypt export-key ./git-crypt-key

# Na jiném počítači / pro kolegu — odemknutí repozitáře klíčem
git-crypt unlock ./git-crypt-key

Správa klíčů — GPG (pro týmy)

Přidání GPG uživatele
# Přidejte GPG klíč kolegy (musí mít veřejný klíč v keyring)
git-crypt add-gpg-user KLÍČ_ID_NEBO_EMAIL

# git-crypt automaticky přidá zašifrovanou kopii klíče do .git-crypt/
# Kolega pak odemkne repozitář svým GPG klíčem:
git-crypt unlock

Ověření stavu šifrování

git-crypt status
# Zobrazí, které soubory jsou šifrované a které ne
git-crypt status
    encrypted: secrets/api.key
not encrypted: README.md
not encrypted: src/main.py

# Zamknout repozitář (šifrované soubory se znovu zakódují)
git-crypt lock
Pozor: git-crypt šifruje pouze obsah souborů — názvy souborů a cesty jsou viditelné pro každého, kdo má přístup k repozitáři. Také: pokud omylem commitnete soubor před nastavením pravidla v .gitattributes, zůstane v historii nešifrovaný (viz § 18 pro vyčištění).
Tipy:
  • Klíčový soubor (git-crypt-key) uchovávejte v password manageru nebo bezpečném úložišti — bez něj jsou data nenávratně ztracená.
  • Přidejte git-crypt-key do .gitignore, aby se klíč nikdy nedostal do repozitáře.
  • Před přidáním nového souboru vždy ověřte pomocí git-crypt status, zda je správně označen k šifrování.

§ 18 Vyčištění Git historie

Pokud do repozitáře omylem projde citlivý soubor (heslo, API klíč, binárka), samo odstranění souboru nestačí — data zůstávají dostupná ve starší historii. Tato sekce popisuje dvě metody vyčištění.

Nevratná operace! Přepis Git historie mění SHA hashe commitů. Pokud repozitář sdílíte s dalšími lidmi, musí všichni smazat svou lokální kopii a znovu klonovat. Vždy si nejprve vytvořte zálohu (git clone --mirror).

Metoda A — Orphan branch (nejrychlejší reset celé historie)

Hodí se tehdy, kdy chcete zachovat aktuální stav souborů, ale celou historii zahodit — například při startu open-source projektu z interního repozitáře.

Kompletní reset historie přes orphan branch
# 1. Vytvoř orphan branch (nová větev bez jakékoli historie)
git switch --orphan clean-main

# 2. Přidej všechny aktuální soubory do staging
git add -A

# 3. Vytvoř nový initial commit
git commit -m "Initial clean commit"

# 4. Smaž starou větev
git branch -D main

# 5. Přejmenuj novou větev na main
git branch -m main

# 6. Force push na GitHub (přepíše vzdálenou historii)
git push origin main --force

# 7. Smaž ostatní vzdálené větve, které už nepotřebuješ
git push origin --delete <název-větve>

Metoda B — git filter-repo (chirurgické odstranění konkrétního souboru)

Hodí se tehdy, kdy chcete zachovat historii, ale z každého commitu vymazat jeden konkrétní soubor (nebo složku).

Odstranění souboru z celé historie pomocí git filter-repo
# Instalace (git filter-repo není součástí Gitu)
brew install git-filter-repo          ← macOS
pip install git-filter-repo           ← cross-platform

# Odstraň soubor z celé Git historie (--invert-paths = "vše kromě")
git filter-repo --path secrets.env --invert-paths

# Odstraň celou složku z celé Git historie
git filter-repo --path config/secrets/ --invert-paths

# Ověř, že soubor v historii opravdu chybí
git log --all --full-history -- secrets.env
← prázdný výstup = soubor byl úspěšně smazán ze všech commitů

# Force push — přepíše vzdálený repozitář
git push origin --force --all
git push origin --force --tags
Po vyčištění vždy:
  • Zneplatněte a rotujte všechna kompromitovaná tajemství (API klíče, hesla) — je možné, že je někdo již stáhl.
  • Na GitHubu kontaktujte podporu pro vynucené smazání cache (cached views).
  • Informujte spolupracovníky — musí smazat lokální klony a znovu klonovat.

§ 16 Cheatsheet — rychlá reference

KategoriePříkazPopis
Nastavení git config --global user.name "X"Nastavit jméno
git config --list --globalZobrazit globální konfiguraci
git config --global core.editor "code --wait"Nastavit VS Code jako editor
Staging git statusStav working directory
git add souborPřidat soubor do staging
git add -pInteraktivní přidávání po částech
git diffZměny na disku oproti staging
git diff --stagedStaging oproti poslednímu commitu
Historie git log --oneline --graph --allKompaktní vizuální log
git show HEADDetail posledního commitu
git blame souborKdo a kdy upravil každý řádek
Vrácení git restore souborZahodit změny na disku (od posl. commitu)
git restore --staged souborVyjmout ze staging (zachová změny)
git reset --soft HEAD~1Zrušit commit, zachovat staging
git revert HEADNový opravný commit (bezpečné)
Tagy git tag v1.0.0 -m "Release 1.0"Annotovaný tag
git push origin --tagsOdeslat tagy na remote
Záchrana git reflogHistorie všech pohybů HEAD (90 dní)
git stash popObnovit naposledy odložené změny

Cloudflare Workers – průvodce pro statický web na vlastní doméně

verze 1.1 Wrangler 3.x macOS 2025-04-02 +URL Rewrite +Git ⚠ Zdroj: Claude – ověř v dokumentaci Cloudflare

Přehled a koncepty

Cloudflare Workers je serverless platforma servírující statické soubory nebo spouštějící kód na globální CDN síti. Pro statický web jsou požadavky zdarma a bez limitu.

Poznámka: Cloudflare Pages byl deprecated v dubnu 2025. Cloudflare doporučuje Workers pro všechny nové projekty.

Klíčové pojmy

PojemPopis
WorkerServerless funkce nebo statický web nasazený na Cloudflare
WranglerCLI nástroj Cloudflare pro správu Workers
wrangler.tomlKonfigurační soubor projektu
Static AssetsStatické soubory (HTML, CSS, JS, obrázky) servírované přímo
RoutesPravidla pro mapování URL na Worker
Custom DomainVlastní doména nebo subdoména napojená na Worker
ZoneDoménová zóna spravovaná Cloudflare
Proxied (oranžový mrak)DNS záznam prochází přes Cloudflare proxy
RedirectHTTP přesměrování — prohlížeč změní adresu
RewriteInterní přepis URL — prohlížeč adresu nezmění

Architektura

Uživatel → DNS (Cloudflare) → Worker (redirect / rewrite / logika) → Static Assets

Předpoklady

Software

  • macOS 13.5+
  • Node.js v20+ — instalace přes nvm nebo brew
  • npm (součást Node.js)
  • Git — pro verzování projektu

Účty a domény

  • Aktivní Cloudflare účetdash.cloudflare.com
  • Doména přidaná do Cloudflare jako zone (nameservery musí ukazovat na Cloudflare)
brew install node git
node --version   # očekáváno v20+

Instalace a přihlášení

mkdir muj-web && cd muj-web
npm init -y
npm install -D wrangler
npx wrangler --version   # ověření
npx wrangler login    # otevře prohlížeč, token se uloží do ~/.wrangler/
npx wrangler whoami   # ověření přihlášení

Struktura projektu

Minimální projekt (statický web)

muj-web/
├── .git/                  ← Git repozitář
├── .gitignore
├── wrangler.toml          ← konfigurace Workers
├── package.json
└── public/
    ├── index.html
    ├── style.css
    └── 404.html

Projekt s Worker scriptem (redirect, rewrite)

muj-web/
├── .git/
├── .gitignore
├── wrangler.toml
├── package.json
├── src/
│   └── worker.js          ← Worker script
└── public/
    ├── index.html
    ├── style.css
    └── 404.html

Konfigurace wrangler.toml

5.1 Čistě statický web

name = "muj-web"
compatibility_date = "2025-04-01"

[assets]
directory = "./public"
not_found_handling = "404-page"

5.2 Statický web s vlastní doménou

name = "muj-web"
compatibility_date = "2025-04-01"

[assets]
directory = "./public"
not_found_handling = "404-page"

[[routes]]
pattern = "www.jan-zak.cz/*"
zone_name = "jan-zak.cz"

[[routes]]
pattern = "jan-zak.cz/*"
zone_name = "jan-zak.cz"

5.3 Statický web na subdoméně

name = "wtest-jan-zak"
compatibility_date = "2025-04-01"

[assets]
directory = "./public"
not_found_handling = "404-page"

[[routes]]
pattern = "wtest.jan-zak.cz/*"
zone_name = "jan-zak.cz"

5.4 Statický web + Worker script (redirect / rewrite)

name = "jan-zak-web"
compatibility_date = "2025-04-01"
main = "src/worker.js"

[assets]
directory = "./public"
not_found_handling = "404-page"

[[routes]]
pattern = "jan-zak.cz/*"
zone_name = "jan-zak.cz"

[[routes]]
pattern = "www.jan-zak.cz/*"
zone_name = "jan-zak.cz"

[[routes]]
pattern = "tools.jan-zak.cz/*"
zone_name = "jan-zak.cz"

Přehled klíčových polí

PolePopisPříklad
nameInterní název Workeru (bez teček)"muj-web"
compatibility_dateDatum kompatibility runtime"2025-04-01"
mainCesta k Worker scriptu"src/worker.js"
assets.directorySložka se statickými soubory"./public"
assets.not_found_handlingChování při 404"404-page"
routes[].patternURL vzor (vždy s /*)"jan-zak.cz/*"
routes[].zone_nameApex doména (zone v Cloudflare)"jan-zak.cz"

Lokální vývoj

npx wrangler dev   # → http://localhost:8787, live reload

Ukázka: public/index.html

<!DOCTYPE html>
<html lang="cs"><head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Jan Novák</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>Jan Novák</h1>
  <nav><a href="/">Úvod</a> <a href="/o-mne.html">O mně</a></nav>
</body></html>

Ukázka: public/404.html

<!DOCTYPE html><html lang="cs"><head><meta charset="UTF-8"><title>404</title></head>
<body><h1>404 – Stránka nenalezena</h1><p><a href="/">Zpět na úvod</a></p></body></html>

Nasazení (deploy)

npx wrangler deploy                 # nasazení na Cloudflare
npx wrangler deployments list       # výpis verzí

Po úspěšném deployi Wrangler vrátí URL ve tvaru https://muj-web.<nazev>.workers.dev. Každý deploy vytváří novou verzi — Cloudflare uchovává posledních 100 verzí.


Vlastní doména a DNS

8.1 Přidání domény do Cloudflare

  1. dash.cloudflare.comAdd a Site → zadej doménu → Free plan
  2. Nastav nameservery dle pokynů Cloudflare u registrátora
  3. Počkej na aktivaci (obvykle do hodiny)

8.2 DNS záznam pro subdoménu (placeholder)

TypNameValueProxy status
AAAAwtest100::Proxied

Pokud CNAME již existuje: Zkontroluj, že je Proxied. Worker přes [[routes]] CNAME nemodifikuje — pouze zachytí provoz. Původní CNAME zůstane zachováno.

dig wtest.jan-zak.cz   # ověření DNS

Přesměrování (redirecty)

Redirecty vyžadují Worker script. Čistý wrangler.toml přesměrování neumí.

9.1 Jednoduchý redirect subdomény

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.hostname === "tools.jan-zak.cz") {
      return Response.redirect("https://jan-zak.cz/tools/jz-tools.html", 301);
    }
    return env.ASSETS.fetch(request);
  }
};

9.2 Více redirectů (tabulkový přístup)

const redirects = {
  "tools.jan-zak.cz": "https://jan-zak.cz/tools/jz-tools.html",
  "blog.jan-zak.cz":  "https://jan-zak.cz/blog/",
  "cv.jan-zak.cz":    "https://jan-zak.cz/dokumenty/cv.pdf",
};

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const target = redirects[url.hostname];
    if (target) return Response.redirect(target, 301);
    return env.ASSETS.fetch(request);
  }
};

9.3 Redirect www → apex (zachování cesty)

if (url.hostname === "www.jan-zak.cz") {
  url.hostname = "jan-zak.cz";
  return Response.redirect(url.toString(), 301);
}

9.4 Redirect s přenesením cesty

// tools.jan-zak.cz/neco → jan-zak.cz/tools/neco
if (url.hostname === "tools.jan-zak.cz") {
  const newUrl = `https://jan-zak.cz/tools${url.pathname}${url.search}`;
  return Response.redirect(newUrl, 301);
}

9.5 Rozdíl mezi 301 a 302

KódTypCachováníPoužití
301TrvalýAnoTrvalé přejmenování, migrace
302DočasnýNeTestování, dočasné přesměrování

Upozornění: 301 redirect si prohlížeč zakešuje. Při testování vždy nejprve používej 302.


URL Rewrite

URL rewrite servíruje jiný obsah, než odpovídá adrese v prohlížeči — adresa v adresním řádku se nemění.

Redirect vs. Rewrite

Redirect (301/302)Rewrite
Adresa v prohlížečiZmění se na cílovou URLZůstane původní
HTTP odpověď301 / 302200 (obsah cíle)
Viditelnost pro uživateleAnoNe
Vhodné proTrvalé přejmenování, SEOHezké URL, skrytí struktury

10.1 Základní rewrite cesty

Uživatel vidí /tools, Worker interně načte /tools/jz-tools.html:

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.pathname === "/tools") {
      url.pathname = "/tools/jz-tools.html";
      return env.ASSETS.fetch(url.toString()); // prohlížeč stále vidí /tools
    }
    return env.ASSETS.fetch(request);
  }
};

10.2 Rewrite subdomény na jinou cestu

Uživatel vidí https://tools.jan-zak.cz, Worker interně servíruje /tools/jz-tools.html:

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.hostname === "tools.jan-zak.cz") {
      const rewriteUrl = new URL(request.url);
      rewriteUrl.hostname = "jan-zak.cz";
      rewriteUrl.pathname = "/tools/jz-tools.html";
      return fetch(rewriteUrl.toString());
    }
    return env.ASSETS.fetch(request);
  }
};

10.3 Tabulkový rewrite více cest

const rewrites = {
  "/tools":   "/tools/jz-tools.html",
  "/cv":      "/dokumenty/jan-zak-cv.pdf",
  "/kontakt": "/stranky/kontaktni-formular.html",
};

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const target = rewrites[url.pathname];

    if (target) {
      const rewriteUrl = new URL(request.url);
      rewriteUrl.pathname = target;
      return env.ASSETS.fetch(rewriteUrl.toString());
    }
    return env.ASSETS.fetch(request);
  }
};

10.4 Kombinace redirect + rewrite v jednom Workeru

const redirects = { "tools.jan-zak.cz": "https://jan-zak.cz/tools" };
const rewrites   = { "/tools": "/tools/jz-tools.html", "/cv": "/dokumenty/cv.pdf" };

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    // 1. Redirect subdomény (prohlížeč změní adresu)
    const redirectTarget = redirects[url.hostname];
    if (redirectTarget) return Response.redirect(redirectTarget, 301);

    // 2. Rewrite cesty (prohlížeč adresu nezmění)
    const rewritePath = rewrites[url.pathname];
    if (rewritePath) {
      const rUrl = new URL(request.url);
      rUrl.pathname = rewritePath;
      return env.ASSETS.fetch(rUrl.toString());
    }

    return env.ASSETS.fetch(request);
  }
};

10.5 Kdy použít redirect a kdy rewrite

ScénářDoporučení
Trvalé přejmenování stránky (SEO)Redirect 301
Hezká URL (/tools místo /tools/jz-tools.html)Rewrite
Subdoména jako alias sekce (transparentní)Rewrite
Subdoména jako alias sekce (viditelný přesun)Redirect
Testování nové verze stránkyRedirect 302
Skrytí interní struktury souborůRewrite

Git a verzování projektu

Git a Wrangler jsou zcela nezávislé nástroje — nedochází mezi nimi ke konfliktům.

Proč nedochází ke konfliktům

NástrojCo spravujeKde ukládá data
GitVerzování souborů projektu.git/ (v adresáři projektu)
WranglerDeploy na Cloudflare, tokeny~/.wrangler/ (globálně, mimo projekt)

Doporučený .gitignore

# npm závislosti
node_modules/

# Wrangler lokální cache
.wrangler/

# macOS
.DS_Store

Co patří do Gitu

Soubor / složkaDo Gitu?Důvod
wrangler.tomlAnoKonfigurační soubor, ne citlivá data
src/worker.jsAnoZdrojový kód
public/AnoStatické soubory webu
package.jsonAnoDefinice projektu
node_modules/NeGenerováno npm install
.wrangler/NeLokální cache Wrangleru
.DS_StoreNemacOS systémový soubor

Praktický důsledek pro rollback: Routes v wrangler.toml se při Cloudflare rollbacku neobnoví — Worker rollback vrátí pouze kód. Verzování wrangler.toml v Gitu to řeší: git restore --source=<commit> -- wrangler.toml + nový deploy.

Inicializace Git repozitáře

cd muj-web
git init
# vytvoř .gitignore
git add .
git commit -m "Initial commit: Cloudflare Workers static site"

Rollback

Cloudflare Workers uchovává posledních 100 verzí pro každý Worker.

npx wrangler deployments list                         # výpis verzí
npx wrangler rollback --message "Důvod rollbacku"     # poslední stabilní
npx wrangler rollback <version-id> --message "Popis"  # konkrétní verze

Rollback přes Dashboard

  1. dash.cloudflare.com → Workers & Pages → vyber Worker
  2. Záložka Deployments → u požadované verze tři tečky → Rollback

Limity rollbacku

OmezeníPopis
Počet verzíPosledních 100 verzí
RoutesRollback nevrátí změny routes — pouze kód
KV / R2 / D1Data se nerolují zpět
SecretsPoužije aktuální hodnoty, ne historické

Praktický důsledek: Routes obnoví Git (git restore --source=<commit> -- wrangler.toml + wrangler deploy), ne Cloudflare rollback.


Další běžné scénáře

13.1 Vlastní HTTP hlavičky (security headers)

Správný vzor: definuj hlavičky jako konstantu a aplikuj je přes pomocnou funkci. Přepisuj jen ty, které CF Assets sám nenastavuje.

const SECURITY_HEADERS = {
  // Zabraňuje MIME sniffingu — prohlížeč respektuje Content-Type bez hádání.
  "X-Content-Type-Options": "nosniff",

  // Vypíná legacy XSS auditor (IE/starý Chrome). Hodnota "1; mode=block" je dnes nebezpečná.
  "X-XSS-Protection": "0",

  // Omezuje obsah Referer při navigaci na jiné domény.
  "Referrer-Policy": "strict-origin-when-cross-origin",

  // Nahrazuje X-Frame-Options — CSP frame-ancestors má vyšší prioritu, XFO se pak ignoruje.
  "Content-Security-Policy": "frame-ancestors 'none'",

  // Zakazuje přístup k browser API, která stránka nepotřebuje.
  "Permissions-Policy": "geolocation=(), camera=(), microphone=()",

  // Izoluje browsing context — mitigace Spectre přes sdílenou paměť.
  "Cross-Origin-Opener-Policy": "same-origin",

  // Zabraňuje načtení zdrojů této domény cross-origin stránkami.
  "Cross-Origin-Resource-Policy": "same-origin",

  // Cache-Control — CF Assets ho sám nenastavuje; 7 dní v prohlížeči i CDN.
  "Cache-Control": "public, max-age=604800",
};

function addSecurityHeaders(response) {
  const headers = new Headers(response.headers);
  for (const [key, value] of Object.entries(SECURITY_HEADERS)) {
    headers.set(key, value);
  }
  return new Response(response.body, { ...response, headers });
}

export default {
  async fetch(request, env) {
    const response = await env.ASSETS.fetch(request);
    return addSecurityHeaders(response);
  },
};
Poznámky:
  • Strict-Transport-Security přidává Cloudflare automaticky — ve Workeru je zbytečná.
  • X-Frame-Options je zastaralé; pokud jsou přítomny oba, prohlížeč ignoruje XFO ve prospěch CSP frame-ancestors.
  • Content-Security-Policy: default-src 'self' je příliš restriktivní pro statické weby načítající fonty nebo CDN skripty — uprav dle potřeby.

13.2 Vynucení HTTPS

Nastavení v dashboardu: SSL/TLS → Edge Certificates → Always Use HTTPS. Worker script není potřeba.

13.3 Základní HTTP autentizace

export default {
  async fetch(request, env) {
    const auth = request.headers.get("Authorization");
    const expected = "Basic " + btoa("uzivatel:heslo"); // → použij env.HESLO

    if (!auth || auth !== expected) {
      return new Response("Přístup odepřen", {
        status: 401,
        headers: { "WWW-Authenticate": 'Basic realm="Sekce"' },
      });
    }
    return env.ASSETS.fetch(request);
  }
};

13.4 Geograficky podmíněný obsah

const country = request.cf?.country;
if (country === "CZ" || country === "SK") {
  if (!url.pathname.startsWith("/cs/")) {
    url.pathname = "/cs" + url.pathname;
    return Response.redirect(url.toString(), 302);
  }
}

13.5 JSON endpoint

if (url.pathname === "/api/status") {
  return new Response(
    JSON.stringify({ status: "ok", timestamp: new Date().toISOString() }),
    { headers: { "Content-Type": "application/json" } }
  );
}

13.6 Zpracování více subdomén pod jedním Workerem

const routes = {
  "jan-zak.cz":       null,
  "www.jan-zak.cz":   "https://jan-zak.cz",
  "tools.jan-zak.cz": "https://jan-zak.cz/tools/jz-tools.html",
  "blog.jan-zak.cz":  "https://jan-zak.cz/blog/",
};

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const target = routes[url.hostname];
    if (target) {
      if (target === "https://jan-zak.cz") {
        url.hostname = "jan-zak.cz";
        return Response.redirect(url.toString(), 301);
      }
      return Response.redirect(target, 301);
    }
    return env.ASSETS.fetch(request);
  }
};

Doporučení a best practices

Konfigurace

  • Vždy používej /* v route pattern — bez hvězdičky Worker neobsluhuje podsložky.
  • Název Workeru (name) nesmí obsahovat tečky — používej pomlčky.
  • compatibility_date nastav na aktuální datum při vytváření projektu; neměň bez důvodu.
  • Udržuj wrangler.toml v Git repozitáři.

DNS a domény

  • Vždy ověř, že DNS záznam je Proxied — bez toho Worker není zavolán.
  • Pro subdomény bez záznamu vytvoř placeholder AAAA 100:: (Proxied).
  • Pokud existuje CNAME, použij [[routes]], ne custom_domain = true.

Redirecty a rewrite

  • Při testování používej 302, na produkci přepni na 301 až po ověření.
  • Pro hezké URL bez změny adresy použij rewrite (env.ASSETS.fetch(rewriteUrl.toString())).

Bezpečnost

  • API klíče a hesla ukládej jako Wrangler secrets, ne přímo do kódu:
npx wrangler secret put MOJE_HESLO   # přístup přes env.MOJE_HESLO
  • Přidej security headers (viz scénář 13.1).
  • Aktivuj Always Use HTTPS v Cloudflare dashboardu.

Git a verzování

  • Verzuj wrangler.toml — routes se při Cloudflare rollbacku neobnoví, Git je má.
  • Přidej node_modules/ a .wrangler/ do .gitignore.
  • Před větší změnou si zapiš version ID (npx wrangler deployments list).

Přehled příkazů Wrangler

PříkazPopis
npx wrangler loginPřihlášení ke Cloudflare
npx wrangler whoamiZobrazení přihlášeného uživatele
npx wrangler logoutOdhlášení od Cloudflare
npx wrangler devLokální dev server (localhost:8787)
npx wrangler deployNasazení Workeru na Cloudflare
npx wrangler deployments listVýpis posledních deploymentů
npx wrangler rollbackRollback na poslední stabilní verzi
npx wrangler rollback <id>Rollback na konkrétní verzi
npx wrangler secret put <NAZEV>Uložení citlivého parametru
npx wrangler secret listVýpis názvů uložených secrets
npx wrangler secret delete <NAZEV>Smazání secretu
npx wrangler tailŽivý log requestů (streaming)
npx wrangler --versionVerze Wrangleru

Řešení častých problémů

Worker není volán po deployi

  • DNS záznam musí existovat a být Proxied.
  • Ověř zone_name — musí odpovídat apex doméně.
  • Route pattern musí obsahovat /*.

Chyba origin_conflict_existing_dns_record

  • Nastává při custom_domain = true s existujícím CNAME.
  • Řešení: použij [[routes]].

404 na všech stránkách kromě indexu

  • Ověř, že assets.directory ukazuje na správnou složku a index.html je přímo v ní.

Redirect neplatí (zakešovaný 301)

  • Zkus anonymní okno nebo vymaž cache prohlížeče. Při testování vždy 302.

Rewrite vrací 404

  • Ověř, že cílový soubor existuje v public/.
  • Předávej URL jako string: env.ASSETS.fetch(url.toString()).

wrangler dev nefunguje (chyba autentizace)

npx wrangler logout && npx wrangler login

Lokální dev nevidí soubory z public/

  • Cesta v assets.directory musí být "./public", nikoli "public".

Git a Wrangler — zdánlivý konflikt

  • Ke konfliktům nedochází. Přidej .wrangler/ a node_modules/ do .gitignore.

Zdroje

DokumentURL
Static Assets – Get Starteddevelopers.cloudflare.com/workers/static-assets/
Wrangler – instalace…/wrangler/install-and-update/
Wrangler – konfigurace…/wrangler/configuration/
Wrangler – příkazy…/wrangler/commands/
Routes…/routing/routes/
Custom Domains…/routing/custom-domains/
Fetch handler (rewrite)…/runtime-apis/handlers/fetch/
Rollbacks…/versions-and-deployments/rollbacks/
Ceny a limity…/platform/pricing/
GitHub Actions pro Workers…/ci-cd/external-cicd/github-actions/