Beetaversioon: sisu on enamasti terviklik ja avalikuks katsetamiseks valmis, kuid vajab veel tehnilist, keelelist ja kasutatavuse kontrolli.

Peatüki vaade

Linux/Unix/macOS käsurea kiirõpik

Praegu loed peatükki Git, GitHub ja töövoog, mis kuulub osasse Osa V: Arendus ja töövood.

Git, GitHub ja töövoog

Loogika

Git ei ole lihtsalt viis faile GitHubi saata. Git hoiab projekti muutuste ajalugu.

Git nimetab üht loogilist ajalookirjet sõnaga commit; selles peatükis kasutame selle kohta ka eestikeelset sõna versioonikirje.

Kõige tähtsam töövoog on:

  1. vaata, mis seisus repo on
  2. vaata, mis täpselt muutus
  3. vali järgmise versioonikirje sisu
  4. salvesta loogiline muutus versioonikirjena
  5. sünkrooni vajadusel kaugrepoga

Git ja GitHub ei ole sama asi:

  • Git on versioonihaldus sinu masinas
  • GitHub on teenus, kus repot jagada, arutada ja üle vaadata

Kiirülevaade

KäskMilleksMida tavaliselt näed
git statusvaata repo seisumuutunud, vahealal olevad ja jälgimata failid
git diffvaata tööpuu muutusi- ja + read jälgitud failides
git add failpane fail vahealaleedukal juhul sageli vaikne
git diff --cachedvaata vaheala sisujärgmisse versioonikirjesse minevad muudatused
git commit -m '...'loo versioonikirjeuue kirje lühikood ja kokkuvõte
git log --onelinevaata ajaluguversioonikirjed ühe rea kaupa
git restore faileemalda tööpuu muudatusfail taastatakse vaheala seisu; salvestamata tööpuumuudatus kaob
git restore --staged faileemalda fail vahealaltsisu jääb alles, vaheala muutub
git switch -c haruloo ja ava uus haruliigud uuele harule
git pull --ff-onlyuuenda puhas haru serveristedasinihe (fast-forward) või selge keeldumine
git push -u origin harusaada haru GitHubiüleslaadimise kokkuvõte

Tüüpilised algaja vead

  • tehakse git add enne, kui muudatus on üle vaadatud
  • arvatakse, et git diff näitab ka täiesti uusi ehk jälgimata faile
  • aetakse segi tööpuu, vaheala ja versioonikirje
  • tehakse git pull määrdunud tööpuuga
  • töötatakse otse main harus, kuigi muudatus võiks olla eraldi harus
  • kasutatakse git push --force ilma aru saamata, kelle ajalugu see muudab

Kolm olekut: tööpuu, vaheala ja versioonikirje

Giti õppimine läheb palju lihtsamaks, kui eristad kolme kohta.

KohtTähendusKontrollkäsk
tööpuusinu failid praegu kettalgit status, git diff
vahealajärgmise versioonikirje ettevalmistusgit diff --cached
versioonikirje (commit)salvestatud loogiline muutusgit log --oneline

Tavaline rütm on:


git status
git diff
git add fail.txt
git diff --cached
git commit -m 'Selge sõnum'

git add ei tähenda veel „saada GitHubi“. See tähendab ainult, et muudatus läheb järgmisse versioonikirjesse.

Esimene harjutusrepo

Harjutamiseks vali uus tühi kataloog, mitte olemasolev repo. Näite git init -b main loob hoidla põhiharuga main; -b määrab algse haru nime.


mkdir -p ~/tmp/git-naide
cd ~/tmp/git-naide
git init -b main
printf 'esimene rida\n' > naide.txt
git status
git add naide.txt
git diff --cached
git commit -m 'Lisa naidefail'
git log --oneline

Pane tähele: uus fail naide.txt on alguses jälgimata. Seetõttu ei näita tavaline git diff veel selle sisu. Pärast git add naide.txt näitab git diff --cached, mis läheb esimesse versioonikirjesse.

Kui git commit kaebab autori identiteedi üle, seadista nimi ja e-post:


git config user.name "Eesnimi Perenimi"
git config user.email "nimi@example.com"

Need seaded kehtivad selles repos; --global muudaks vaikeseadet kõigis sinu repodes. Nimi ja e-post salvestatakse versioonikirjetesse ning avaliku repo puhul muutuvad avalikuks. See ei ole GitHubi sisselogimine. Seejärel proovi git commit uuesti.

Muudatuse ülevaatamine

Kui fail on juba Gitis jälgimisel, näitab git diff tööpuu muutust.


printf 'teine rida\n' >> naide.txt
git status
git diff

Diffi lugemise algreegel:

  • - tähendab eemaldatud rida
  • + tähendab lisatud rida
  • ülejäänud read on ümbrus ehk kontekst

Enne käsku git commit kontrolli ka vaheala:


git add naide.txt
git diff --cached
git commit -m 'Lisa teine rida'

Hea harjumus:

  • enne git add: git diff
  • enne git commit: git diff --cached
  • enne tõmbekutse (pull request) avamist: vaata kogu muudatus veel kord üle

Igapäevane põhivoog

Kui repo on juba olemas ja töötad GitHubiga, on rahulik põhivoog selline:


git status
git switch main
git pull --ff-only
git switch -c parandus

Kui sinu repo põhiharu nimi on master, kasuta nendes näidetes main asemel master.

Seejärel tee muudatused. Enne versioonikirje loomist:


git status
git diff
git add fail1 fail2
git diff --cached
git commit -m 'Paranda näited Git peatükis'
git push -u origin parandus

Miks just nii:

  • git status näitab, kas tööpuu on puhas
  • git pull --ff-only uuendab põhiharu ainult siis, kui seda saab teha edasinihkena
  • git switch -c parandus hoiab muudatuse eraldi harus
  • git diff ja git diff --cached vähendavad juhusliku versioonikirje riski

Kui git pull --ff-only keeldub, ära lisa kohe keerulisemaid lippe. Tee esmalt git status ja vaata, kas sul on kohalikke versioonikirjeid või pooleliolevaid muudatusi.

Haru ehk branch

Haru (branch) on sama projekti eraldi arenguliin.

Tüüpiline mõtteviis:

  • main on põhirida
  • väike parandus tehakse eraldi harus
  • hiljem ühendatakse valmis haru tõmbekutse (pull request) kaudu põhiharuga

Põhikäsud:


git branch
git switch -c parandused-logides
git switch main
git branch -d parandused-logides

Siin:

  • git branch näitab harusid; tärn näitab praegust haru
  • git switch -c nimi loob uue haru ja liigub sinna
  • git switch main liigub olemasolevale harule
  • git branch -d nimi kustutab kohaliku haru, kui see on ühendatud

Vanemates juhendites näed sageli kuju:


git checkout -b parandus

See tähendab sama, mis git switch -c parandus, aga switch on algajale selgem: see ütleb otse, et vahetad haru.

Kaugrepo: clone, fetch, pull, push

Kaugrepo on sama repo serveris, näiteks GitHubis. Vaikimisi nimi on sageli origin.

Kui sul ei ole repot veel kohalikus masinas:


git clone git@github.com:kasutaja/projekt.git
cd projekt
git status

See kuju kasutab SSH-d. Kui SSH-võtmed ei ole veel seadistatud, pakub GitHub sama repo jaoks ka algusega https://... kloonimisaadressi.

Kui tahad ainult teada saada, mis serveris muutus, kasuta:


git fetch origin
git log --oneline --graph --decorate --all -n 20

git fetch uuendab infot kaugrepo kohta, aga ei muuda sinu praegust tööharu.

Kui tahad puhta kohaliku haru serveriga samasse seisu tuua:


git pull --ff-only

Kui sul on oma haru valmis ja tahad selle GitHubi saata:


git push -u origin parandus

Kui tööpuu pole puhas

Enne haru vahetamist ning käskude pull või rebase kasutamist kontrolli:


git status

Järgmine käsk kustutab faili tööpuus tehtud, vahealale lisamata muudatused. git restore fail.txt taastab faili vahealalt, mitte tingimata viimasest versioonikirjest. Vaata enne git diff ja jäta vajalik töö alles:


git restore fail.txt

Kui tahad faili vahealalt eemaldada, kuid sisu alles jätta:


git restore --staged fail.txt

Kui tahad poolelioleva töö korraks kõrvale panna:


git stash push -m 'pooleli enne pulli'
git pull --ff-only
git stash pop

Vaikimisi jätab stash jälgimata failid kõrvale; nende kaasamiseks on valik -u. stash pop võib tekitada konflikti ning jätab sel juhul kirje alles. stash on ajutine sahtel, mitte pikaajaline hoiukoht. Kui töö on sisuline, salvesta see pigem käsuga git commit, mitte ära jäta muudatusi nädalateks stash-i.

.gitignore

Kõiki faile ei tasu Giti lisada. Paroolid, privaatvõtmed ja kohalikud saladused ei kuulu ka privaatsesse reposse. Kui saladus on juba avaldatud, tuleb see tühistada või vahetada; failist kustutamine ei eemalda seda ajaloost.

Tüüpiliselt jäetakse välja:

  • virtuaalkeskkonnad, näiteks .venv/
  • vahemälud, näiteks __pycache__/
  • koostamisväljundid, näiteks dist/
  • ajutised logid, näiteks *.log

Lihtne näide:


cat > .gitignore <<'EOF'
.venv/
__pycache__/
dist/
*.log
.env
EOF
git status

Kui fail on juba Giti lisatud, siis ainult .gitignore ei eemalda seda automaatselt repost. .gitignore takistab eelkõige uute sobivate failide juhuslikku lisamist.

merge ja rebase

merge ja rebase panevad kaks ajalugu uuesti kokku, aga teevad seda eri moodi.

TegevusMõteMillal kasutada
mergesäilitab mõlema haru ajaloovalmis haru ühendamisel
rebasetõstab sinu versioonikirjed teise haru lõppuoma parandusharu korrastamisel

Näide: oled harus parandus ja tahad sellesse ühendada värske haru main:


git fetch origin
git switch parandus
git rebase origin/main

Näide: tahad valmis haru main sisse ühendada:


git switch main
git pull --ff-only
git merge parandus

Meeskonnareegel:

  • oma parandusharus võib enne tõmbekutse esitamist sageli kasutada käsku rebase
  • ära kasuta käsku rebase harus, millele teised juba oma tööd rajavad, kui see ei ole kokku lepitud
  • ühise main haru ajalugu tuleb käsitleda eriti ettevaatlikult

Konfliktid

Konflikt tekib siis, kui Git ei oska kahte muudatust ise kokku panna.

Failis võib olla selline koht:


    <<<<<<< HEAD
minu praegune tekst
    =======
teisest harust tulnud tekst
    >>>>>>> origin/main

See tähendab:

  • <<<<<<< HEAD all on sinu praeguse haru versioon
  • ======= eraldab kaks varianti
  • >>>>>>> origin/main all on teise haru versioon

Konfliktimärgid algavad päris failis rea algusest. Ülal on ühendamise (merge) näide. Ümbertõstmise (rebase) ajal võib HEAD tähistada hoopis alust, mille peale sinu versioonikirjet uuesti rakendatakse: loe mõlemat varianti, mitte ära vali neid sildi „minu“ järgi.

Lahendamine:

  1. ava fail redaktoris
  2. tee valmis õige lõpptekst
  3. kustuta konfliktimärgid
  4. kontrolli faili sisu
  5. lisa fail vahealale

Näiteks:


git status
nano fail.txt
git add fail.txt

Kui konflikt tekkis käsu git merge ajal:


git commit

Kui konflikt tekkis käsu git rebase ajal:


git rebase --continue

Kui läksid valesse suunda, katkesta ainult käimasolev tegevus:


git merge --abort
git rebase --abort

Kasuta neist ainult seda käsku, mis vastab parasjagu käimasolevale tegevusele.

Mida mitte teha pimesi

Need käsud võivad olla õiged, aga neid ei tasu kasutada paanikas:

  • git reset --hard
  • git clean -fd
  • git push --force
  • git branch -D haru

Rahulikum kontrolljärjekord on:

  1. git status
  2. git diff
  3. git diff --cached
  4. vajadusel küsi abi või tee koopia enne hävitavat käsku

Kui force-push on tõesti vajalik, peaks see olema meeskonnas kokku lepitud ja piirduma tavaliselt oma parandusharuga, mitte ühise haruga main.

GitHub: issue ja pull request

GitHubis seotakse muudatus tavaliselt arutelukoha või ülesandega.

Põhimõisted:

  • issue ehk probleemikirje on ülesanne, viga või aruteluteema
  • pull request ehk tõmbekutse esitab muudatusettepaneku ülevaatamiseks ja ühendamiseks
  • review ehk koodiülevaatus on teiste tagasiside tõmbekutse kohta
  • checklist ehk kontroll-loend on Markdowni märkeruutudega loend

Lihtne probleemikirje kirjeldus:


## Probleem

Peatükis 09 on `cat` ja `less` vahe liiga uduselt seletatud.

## Oodatud tulemus

Lugeja saab aru, millal kasutada `cat` ja millal `less`.

## Kontroll

- [ ] näide on peatükis parandatud
- [ ] koostamine õnnestub

Hea tõmbekutse ehk muudatusettepanek vastab kolmele küsimusele:

  • mis probleem lahendati
  • kuidas seda lahendati
  • kuidas kontrolliti, et lahendus töötab

Tüüpiline GitHubi töövoog:

  1. vali probleemikirje või kirjuta probleem lühidalt lahti
  2. loo selle jaoks haru, näiteks fix-cat-less
  3. tee väike loogiline muudatus
  4. loo selge sõnumiga versioonikirje
  5. saada haru käsuga git push GitHubi
  6. ava tõmbekutse (pull request)
  7. vasta ülevaatuskommentaaridele uute versioonikirjetega
  8. pärast ühendamist kustuta tööharu

Versioonikirje või tõmbekutse kirjelduses saab probleemikirjele viidata:


Fixes #12
Closes #12
Refs #12

Väike lõppharjutus

Tee ajutises repos üks väike töövoog läbi:


cd ~/tmp/git-naide
git switch -c kolmas-rida
printf 'kolmas rida\n' >> naide.txt
git diff
git add naide.txt
git diff --cached
git commit -m 'Lisa kolmas rida'
git log --oneline --graph --decorate -n 5

Kui tahad harjutusrepo hiljem lihtsalt ära unustada, jäta see ~/tmp alla või kustuta siis, kui oled kindel, et seal pole vajalikku tööd.

Spikker

Git-käskude visuaalne kaart ja pikem tekstiline meelespea on lisas Lisa B: spikrite register.

Minitest

  1. Selgita, mis vahe on tööpuul, vahealal ja commit-kirjel ehk versioonikirjel.
  2. Miks ei näita git diff uue jälgimata faili sisu?
  3. Millal vaatad git diff --cached?
  4. Miks on git switch -c parandus algajale selgem kui git checkout -b parandus?
  5. Mis vahe on git fetch ja git pull --ff-only vahel?
  6. Millal kasutaksid git restore --staged fail.txt?
  7. Kirjuta tõmbekutse (pull request) lühikirjeldus kujul: probleem, lahendus, kontroll.

Lisalugemine

Selle teema usaldusväärsemad viited leiad lisast Lisa E: usaldusväärsed viited ja lisalugemine.

Peatüki täisspikker

Edasijõudnu

Eesmärk

Git hoiab muutuste ajalugu; erista tööpuud, vaheala ja versioonikirjet ning vaata muudatused enne üle.

Põhikujud

  • git statusvaata seis
  • git diffmuutused tööpuus
  • git diff --cachedmuutused vahealal
  • git add fail.txtlisa vahealale
  • git commit -m '...'loo versioonikirje
  • git switch -c parandusloo haru
  • git pull --ff-onlyuuenda puhtalt
  • git push -u origin parandussaada haru
  • git restore --staged fail.txteemalda vahealalt

Olulisemad lipud, märgid ja kiirnupud

  • HEADpraegune tipp
  • mainpõhirida
  • originkaugrepo
  • vahealajärgmise versioonikirje sisu