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ů.
§ 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.
# 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
# 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
Doporučeno: Homebrew. macOS sice Git obsahuje, ale jeho verze je zastaralá (Apple ji neaktualizuje). Homebrew nainstaluje aktuální verzi.
# 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
# Nainstaluje Git spolu s vývojářskými nástroji Apple xcode-select --install # Nevýhoda: starší verze Gitu, aktualizace jen s macOS updatem
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.
sudo apt update sudo apt install git # Nebo kompletní balík s extra nástroji: sudo apt install git-all
sudo dnf install git
sudo pacman -S git
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.
| Klient | Typ | OS | Pro koho | Cena |
|---|---|---|---|---|
| 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é |
§ 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).
# 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
--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.
# 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.
# 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
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
| Zkratka | Co znamená v praxi |
|---|---|
| HEAD~1 | „o jeden commit zpět" — HEAD~3 = o tři zpět. HEAD je vždy aktuální pozice. |
| origin | Výchozí název vzdáleného repozitáře (GitHub/GitLab). Nastavuje se automaticky při git clone. |
| origin/main | Lokální záložka stavu větve main na serveru — aktualizuje se jen při git fetch. |
| upstream | Vazba mezi vaší lokální větví a větví na serveru. Po nastavení (git push -u origin main) stačí psát jen git push. |
| a1b2c3d | Zkrá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.
| Typ | Co obsahuje | Příklad |
|---|---|---|
| blob | Obsah jednoho souboru — jen data, bez názvu a cesty | Obsah README.md |
| tree | Adresář: seznam názvů + hash blobu nebo podadresáře | Složka src/ |
| commit | Snímek projektu: hash tree, hash předchozího commitu, autor, čas, zpráva | Každý váš git commit |
| tag | Nepohyblivý, pojmenovaný ukazatel na commit | v1.0.0 |
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
.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ů.
jak je vidíte v editoru
změn k zapsání
ve složce .git/
sdíleno s týmem
| Termín | Vysvětlení | Analogie |
|---|---|---|
| Working Directory | Soubory na disku — jak je vidíte v editoru. Git je sleduje, ale zatím nic nezapsal. | Rozepsaný dokument |
| Index / Staging | Př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í |
| Commit | Trvalý, 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 |
| HEAD | Speciální reference říkající „kde teď jsem". Ukazuje na aktuální větev. | „Jste zde" na mapě |
| Remote | Vzdá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 |
| Tag | Nepohyblivý štítek na commitu — neposouvá se při nových commitech. Pro označení verzí. | Trvalá etiketa |
§ 07 Commit workflow
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
# 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)
# 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.
# 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
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
| Aspekt | git merge | git rebase |
|---|---|---|
| Co udělá | Vytvoří nový „merge commit" se dvěma rodiči | Přepíše commity vaší větve od vrcholu jiné větve |
| Výsledná historie | Zachová skutečný průběh vývoje | Lineární — jako by větvení nebylo |
| Bezpečné na sdílenou větev? | ✓ Ano | ✗ Ne — přepíše hashe |
| Kdy použít | Integrace 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.
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.
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í.
Git ohlásí konflikt
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
Otevřete soubor — Git v něm označil obě verze
Sekce od <<<<<<< HEAD po ═══ je vaše verze. Sekce od ═══ po >>>>>>> je příchozí verze.
Ručně upravte soubor — vyberte nebo zkombinujte obě verze
Smažte všechny markery (<<<<<<<, =======, >>>>>>>) a ponechte výsledný kód:
Označte soubor jako vyřešený a dokončete commit
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
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
main, develop ani jiné společné větve. Pouze vaše vlastní feature větve.
§ 10 Remote a sdílení s týmem
| Příkaz | Co dělá | Mění lokální větve? |
|---|---|---|
| git fetch | Stáhne nové commity ze serveru, aktualizuje origin/main | Ne |
| git pull | fetch + automatický merge do aktuální větve | Ano |
| git push | Odešle lokální commity na server | — |
# 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
# 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
.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.
# 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"
.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)
| Prvek UI | Co znamená |
|---|---|
| Staged Changes | Soubory přidané do staging (git add) — půjdou do příštího commitu |
| Changes | Upravené soubory, které ještě nejsou ve staging |
| A / M / D / U | Added / Modified / Deleted / Untracked — stav souboru |
| ↑2 ↓0 | Stavový řádek: máte 2 lokální commity, které jste nepushnuli; 0 stažených ze serveru |
| ⎇ main | Aktuální větev — kliknutím ji změníte nebo vytvoříte novou |
| Pole pro zprávu commitu | Sem napište zprávu a stiskněte Ctrl+Enter (nebo Cmd+Enter na macOS) pro commit |
Ikona ✓ v panelu | Commit tlačítko (alternativa k Ctrl+Enter) |
Ikona … v panelu | Rozbalovací 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.
| Operace | Pří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 → Branch → Merge Branch… |
| Stash (odložit změny) | git stash push -m "popis" | … menu → Stash → Stash All Changes |
| Stash pop (obnovit) | git stash pop | … menu → Stash → Apply 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ší |
§ 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)
{ "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+P → Git 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
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
{ // 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
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:
| Panel | Obsah | Odpovídá |
|---|---|---|
| Incoming (vlevo) | Verze přicházející z mergované větve | Sekce >>>>>>> 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 podobu | Co bude zapsáno |
Postup řešení konfliktu krok za krokem
Otevřete Merge Editor
VS Code zobrazí v horní části souboru banner s konfliktem. Klikněte na tlačítko Resolve in Merge Editor.
Pro každý konflikt vyberte akci
Nad každým konfliktem se zobrazí tlačítka — vyberte jedno:
| Tlačítko | Co udělá |
|---|---|
| Accept Current | Zachová vaši verzi (pravý panel) |
| Accept Incoming | Přijme příchozí verzi (levý panel) |
| Accept Both | Vloží obě verze za sebou (nejdřív Current, pak Incoming) |
| (ruční editace) | Klikněte přímo do panelu Result a upravte text libovolně |
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.
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.
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.
§ 15 Troubleshooting — časté problémy
💥 Potřebuji vrátit poslední commit (ale zachovat změny)
# 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
# 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í.
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í".
! [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
# 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í.
# 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
# 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
# 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
# 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 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ř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í
# 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
.gitattributes, zůstane v historii nešifrovaný (viz § 18 pro vyčištění).
- 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-keydo.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í.
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.
# 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).
# 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
- 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
| Kategorie | Příkaz | Popis |
|---|---|---|
| Nastavení | git config --global user.name "X" | Nastavit jméno |
| git config --list --global | Zobrazit globální konfiguraci | |
| git config --global core.editor "code --wait" | Nastavit VS Code jako editor | |
| Staging | git status | Stav working directory |
| git add soubor | Přidat soubor do staging | |
| git add -p | Interaktivní přidávání po částech | |
| git diff | Změny na disku oproti staging | |
| git diff --staged | Staging oproti poslednímu commitu | |
| Historie | git log --oneline --graph --all | Kompaktní vizuální log |
| git show HEAD | Detail posledního commitu | |
| git blame soubor | Kdo a kdy upravil každý řádek | |
| Vrácení | git restore soubor | Zahodit změny na disku (od posl. commitu) |
| git restore --staged soubor | Vyjmout ze staging (zachová změny) | |
| git reset --soft HEAD~1 | Zrušit commit, zachovat staging | |
| git revert HEAD | Nový opravný commit (bezpečné) | |
| Tagy | git tag v1.0.0 -m "Release 1.0" | Annotovaný tag |
| git push origin --tags | Odeslat tagy na remote | |
| Záchrana | git reflog | Historie všech pohybů HEAD (90 dní) |
| git stash pop | Obnovit naposledy odložené změny |
📚 Zdroje a další čtení
Pro Git Book — oficiální, zdarma online (git-scm.com) Git Reference Manual — git-scm.com/docs Git for Windows — gitforwindows.org VS Code Source Control dokumentace — code.visualstudio.com Conventional Commits — specifikace zpráv commitů GitHub: Nastavení SSH klíče — docs.github.comCloudflare Workers – průvodce pro statický web na vlastní doméně
Obsah
- Přehled a koncepty
- Předpoklady
- Instalace a přihlášení
- Struktura projektu
- Konfigurace wrangler.toml
- Lokální vývoj
- Nasazení (deploy)
- Vlastní doména a DNS
- Přesměrování (redirecty)
- URL Rewrite NEW
- Git a verzování NEW
- Rollback
- Další běžné scénáře
- Doporučení a best practices
- Přehled příkazů Wrangler
- Řešení častých problémů
- Zdroje
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
| Pojem | Popis |
|---|---|
| Worker | Serverless funkce nebo statický web nasazený na Cloudflare |
| Wrangler | CLI nástroj Cloudflare pro správu Workers |
| wrangler.toml | Konfigurační soubor projektu |
| Static Assets | Statické soubory (HTML, CSS, JS, obrázky) servírované přímo |
| Routes | Pravidla pro mapování URL na Worker |
| Custom Domain | Vlastní doména nebo subdoména napojená na Worker |
| Zone | Doménová zóna spravovaná Cloudflare |
| Proxied (oranžový mrak) | DNS záznam prochází přes Cloudflare proxy |
| Redirect | HTTP přesměrování — prohlížeč změní adresu |
| Rewrite | Interní 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
nvmnebobrew - npm (součást Node.js)
- Git — pro verzování projektu
Účty a domény
- Aktivní Cloudflare účet — dash.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í
| Pole | Popis | Příklad |
|---|---|---|
name | Interní název Workeru (bez teček) | "muj-web" |
compatibility_date | Datum kompatibility runtime | "2025-04-01" |
main | Cesta k Worker scriptu | "src/worker.js" |
assets.directory | Složka se statickými soubory | "./public" |
assets.not_found_handling | Chování při 404 | "404-page" |
routes[].pattern | URL vzor (vždy s /*) | "jan-zak.cz/*" |
routes[].zone_name | Apex 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
- dash.cloudflare.com → Add a Site → zadej doménu → Free plan
- Nastav nameservery dle pokynů Cloudflare u registrátora
- Počkej na aktivaci (obvykle do hodiny)
8.2 DNS záznam pro subdoménu (placeholder)
| Typ | Name | Value | Proxy status |
|---|---|---|---|
| AAAA | wtest | 100:: | 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ód | Typ | Cachování | Použití |
|---|---|---|---|
| 301 | Trvalý | Ano | Trvalé přejmenování, migrace |
| 302 | Dočasný | Ne | Testová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či | Změní se na cílovou URL | Zůstane původní |
| HTTP odpověď | 301 / 302 | 200 (obsah cíle) |
| Viditelnost pro uživatele | Ano | Ne |
| Vhodné pro | Trvalé přejmenování, SEO | Hezké 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ánky | Redirect 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ástroj | Co spravuje | Kde ukládá data |
|---|---|---|
| Git | Verzování souborů projektu | .git/ (v adresáři projektu) |
| Wrangler | Deploy 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žka | Do Gitu? | Důvod |
|---|---|---|
wrangler.toml | Ano | Konfigurační soubor, ne citlivá data |
src/worker.js | Ano | Zdrojový kód |
public/ | Ano | Statické soubory webu |
package.json | Ano | Definice projektu |
node_modules/ | Ne | Generováno npm install |
.wrangler/ | Ne | Lokální cache Wrangleru |
.DS_Store | Ne | macOS systémový soubor |
Praktický důsledek pro rollback: Routes v
wrangler.tomlse při Cloudflare rollbacku neobnoví — Worker rollback vrátí pouze kód. Verzováníwrangler.tomlv 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
- dash.cloudflare.com → Workers & Pages → vyber Worker
- Záložka Deployments → u požadované verze tři tečky → Rollback
Limity rollbacku
| Omezení | Popis |
|---|---|
| Počet verzí | Posledních 100 verzí |
| Routes | Rollback nevrátí změny routes — pouze kód |
| KV / R2 / D1 | Data se nerolují zpět |
| Secrets | Použ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-Securitypřidává Cloudflare automaticky — ve Workeru je zbytečná.X-Frame-Optionsje zastaralé; pokud jsou přítomny oba, prohlížeč ignoruje XFO ve prospěch CSPframe-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_datenastav na aktuální datum při vytváření projektu; neměň bez důvodu.- Udržuj
wrangler.tomlv 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]], necustom_domain = true.
Redirecty a rewrite
- Při testování používej
302, na produkci přepni na301až 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říkaz | Popis |
|---|---|
npx wrangler login | Přihlášení ke Cloudflare |
npx wrangler whoami | Zobrazení přihlášeného uživatele |
npx wrangler logout | Odhlášení od Cloudflare |
npx wrangler dev | Lokální dev server (localhost:8787) |
npx wrangler deploy | Nasazení Workeru na Cloudflare |
npx wrangler deployments list | Výpis posledních deploymentů |
npx wrangler rollback | Rollback 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 list | Výpis názvů uložených secrets |
npx wrangler secret delete <NAZEV> | Smazání secretu |
npx wrangler tail | Živý log requestů (streaming) |
npx wrangler --version | Verze 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 = trues existujícím CNAME. - Řešení: použij
[[routes]].
404 na všech stránkách kromě indexu
- Ověř, že
assets.directoryukazuje na správnou složku aindex.htmlje 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.directorymusí být"./public", nikoli"public".
Git a Wrangler — zdánlivý konflikt
- Ke konfliktům nedochází. Přidej
.wrangler/anode_modules/do.gitignore.
Zdroje
| Dokument | URL |
|---|---|
| Static Assets – Get Started | developers.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/ |