Soukromý repozitář na GitHubu pro aplikaci za deset minut, a pořádně
Než začnete
Takto postupujeme, když se mobilní nebo webová aplikace vyvíjela lokálně s jediným „Initial commit“ a teď potřebuje zálohu, historii a stabilní větev. Počítá s shellem na Macu nebo Linuxu, s Gitem a s GitHub CLI přihlášeným k účtu, který bude repozitář vlastnit.
gh auth status
git --version
Soukromý repozitář, větev main jen s otestovanými vydáními, dev pro všechno ostatní a v historii nic, co mělo zůstat na notebooku.
Pravidla review pull requestů, CI a monorepa. Ty přijdou později v seriálu.
1. Audit pracovního stromu
Vypište, co by Git commitnul, a prohlédněte si každý řádek, který nepoznáváte. Velké binární soubory, generované složky a zatoulané soubory se ve dlouhých seznamech snadno ztratí.
git status --short
git status --short | wc -l
du -sh */ | sort -h | tail
Co jsme takto našli v reálných projektech: referenční JPEG odhozený do kořene projektu před měsíci, generované složky ios/ a android/ z Expo prebuildu, složku release/ se snímky obrazovky pro obchody a složku s poznámkami psanými pro vývojáře, ne pro veřejnost.
# confirm what a file is before deciding
file 0.jpg
git check-ignore -v ios android || echo "not ignored"
node_modules, hledejte klíče API, soukromé klíče a soubory servisních účtů. Pokud nějaký najdete, vyměňte ho; klíč, který kdy byl v commitu, je prozrazený, i když commit později přepíšete.grep -rln 'AIza\|BEGIN PRIVATE\|"private_key"' --exclude-dir=node_modules --exclude-dir=ios --exclude-dir=android . || echo "clean"
2. Rozhodněte, co nikdy neopustí počítač
Všechna vyloučení dejte hned do .gitignore, ať je nikdo, ani vy za půl roku, nemůže omylem přidat příkazem git add -A. Náš základ pro Expo vypadá takto:
node_modules/
.expo/
/ios
/android
.test-build/
*.jks
*.p8
*.p12
*.key
*.mobileprovision
.env*.local
google-play-service-account.json
marketplace/out/
# internal notes, audit findings and handoff files — local only
/improvements/
Poslední pravidlo je rozhodnutí o zásadách, ne technická záležitost. Interní poznámky z auditu podrobně popisují slabiny a jsou psané tónem určeným týmu. Patří do zálohy, ne do repozitáře, který se jednou může sdílet s klientem nebo dodavatelem, případně zveřejnit.
Soubory, které prostě nejsou součástí produktu, třeba referenční obrázek ke skice loga, vůbec nepřidávejte. Nemažte je ani neignorujte; nechte je nesledované a ať vám je připomíná git status.
3. První skutečný commit
Přidejte vše do indexu, vyjměte výjimky a před commitem si seznam ještě jednou přečtěte.
git add -A
git reset -q 0.jpg # untracked by choice
git status --short | grep -v '^??' # what the commit will contain
Zprávu pište pro člověka, který repozitář otevře za rok. Napište, co projekt je a v jakém je stavu, ne „wip“.
git commit -F - <<'MSG'
Auto Hlídač: audit findings applied, simulator verification, Xcode 27 support
Complete Expo SDK 57 application (expo-router, SQLite, local notifications,
parking location) with store assets. Verified: typecheck, 74 tests, Maestro
flows on iPhone 17 (iOS 27) and Pixel 3a (API 34). Open items: Google Maps
key, App Store Connect app ID.
MSG
4. Vytvoření repozitáře a push
Jeden příkaz vytvoří soukromý repozitář pod vaším účtem, přidá ho jako origin a pushne aktuální větev:
gh repo create coolsoft-example/AutoHlidac --private --source=. --remote=origin --push
git remote -v
git status -sb
Pokud repozitář už existuje, přidejte vzdálený repozitář ručně:
git remote add origin https://github.com/coolsoft-example/AutoHlidac.git
git push -u origin main
gh repo view --json visibility,defaultBranchRef ohlásí PRIVATE a main a git status -sb ukáže ## main...origin/main.5. Dvě větve: dev pro práci, main pro vydání
Pro samostatného vývojáře nebo malý tým stačí dvě dlouhodobé větve a je to levnější než plný Git Flow. Pravidlo je jednoduché: main dostává jen otestovaný kód, dev všechno ostatní a pracovní kopie zůstává na dev.
git checkout -b dev
git push -u origin dev
| Větev | Kdo pushuje | Kdy |
|---|---|---|
| dev | Kdokoli z týmu, přímo | Průběžně. Force push se toleruje, dokud se funkce tvaruje. |
| main | Jen fast-forward merge z dev |
Po dokončení testování. Nikdy se nepřepisuje a nikdy nemaže. |
# release: fast-forward main to the tested dev commit
git checkout main
git merge --ff-only dev
git push origin main
git checkout dev
Nechte main jako výchozí větev na GitHubu, ať klony a odkazy míří na stabilní kód.
6. Vraťte push, kterého litujete, dokud je to ještě snadné
Pár minut po prvním pushi jsme si všimli, že s ním odešla i složka s interními poznámkami. To je jediný okamžik, kdy je přepsání main správné rozhodnutí: repozitář je pár vteřin starý, nikdo ho neklonoval a alternativou je historie, která složku nese navždy.
git rm -r -q --cached improvements
printf '\n# internal notes — local only\n/improvements/\n' >> .gitignore
git add .gitignore
git commit --amend --no-edit
git push --force-with-lease origin main
git ls-files improvements | wc -l # must print 0
--force-with-lease odmítne přepsat vzdálenou větev, která se od posledního fetche pohnula, což je pojistka za předpokladu, že ho nikdo další nemá. Jakmile je větev sdílená, odstraňte soubory novým commitem a smiřte se s tím, že je historie uchová, nebo vyměňte vše, co se prozradilo.7. Chraňte main bez GitHub Pro
Pravidla ochrany větví na GitHubu nejsou u soukromých repozitářů v bezplatném plánu dostupná:
$ gh api -X PUT repos/OWNER/REPO/branches/main/protection --input rules.json
Upgrade to GitHub Pro or make this repository public to enable this feature. (HTTP 403)
Stejné dvě záruky, tedy žádný force push a žádné smazání main, lze vynutit lokálně hookem pre-push. Hook se neverzuje (.git/hooks je pro každý klon zvlášť), takže ho zkopírujte do každého klonu, který smí pushovat.
cat > .git/hooks/pre-push <<'HOOK'
#!/bin/sh
# Local stand-in for branch protection: refuse force pushes and deletion of main.
zero=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha; do
[ "$remote_ref" = "refs/heads/main" ] || continue
if [ "$local_sha" = "$zero" ]; then
echo "pre-push: deleting main is not allowed." >&2
exit 1
fi
if [ "$remote_sha" != "$zero" ] && ! git merge-base --is-ancestor "$remote_sha" "$local_sha" 2>/dev/null; then
echo "pre-push: force push to main is not allowed; push fast-forward only, develop on dev." >&2
exit 1
fi
done
exit 0
HOOK
chmod +x .git/hooks/pre-push
Vyzkoušejte ho bez zásahu do vzdáleného repozitáře tím, že hooku předáte stejné řádky, jaké by mu poslal Git:
H=$(git rev-parse HEAD); P=$(git rev-parse HEAD~1); Z=0000000000000000000000000000000000000000
printf 'refs/heads/main %s refs/heads/main %s\n' $H $P | .git/hooks/pre-push; echo "fast-forward rc=$?" # 0
printf 'refs/heads/main %s refs/heads/main %s\n' $P $H | .git/hooks/pre-push; echo "force rc=$?" # 1
printf '(delete) %s refs/heads/main %s\n' $Z $H | .git/hooks/pre-push; echo "delete rc=$?" # 1
printf 'refs/heads/dev %s refs/heads/dev %s\n' $P $H | .git/hooks/pre-push; echo "dev force rc=$?" # 0
main je pořád možné příkazem git push --no-verify. O to jde: nebezpečná akce vyžaduje napsat úmysl, takže se nemůže stát reflexem.Kontrolní seznam
- Pracovní strom prověřen, zatoulané soubory určeny, kontrola tajemství čistá.
.gitignorepokrývá generované nativní složky, klíče, lokální soubory s prostředím a interní poznámky.- První commit popisuje projekt a jeho stav.
- Soukromý repozitář vytvořen příkazem
gh repo create --private --source=. --remote=origin --push. - Větev
devvytvořena a pushnuta; pracovní kopie zůstává nadev; výchozí větev jemain. - Cokoli, čeho lze litovat, odstraněno přes amend a
--force-with-lease, než to někdo naklonoval. - Hook
pre-pushnainstalován a vyzkoušen v každém klonu, který pushuje.
Dál v seriálu: kontrolní seznam vydání pro fast-forward dev do main se značkami a co dělat, když na dev pracují dva lidé najednou.
Nic tu není.
Zatím sem nebyl vložen žádný komentář.