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:
- vaata, mis seisus repo on
- vaata, mis täpselt muutus
- vali järgmise versioonikirje sisu
- salvesta loogiline muutus versioonikirjena
- sünkrooni vajadusel kaugrepoga
Git ja GitHub ei ole sama asi:
Giton versioonihaldus sinu masinasGitHubon teenus, kus repot jagada, arutada ja üle vaadata
Kiirülevaade
| Käsk | Milleks | Mida tavaliselt näed |
|---|---|---|
git status | vaata repo seisu | muutunud, vahealal olevad ja jälgimata failid |
git diff | vaata tööpuu muutusi | - ja + read jälgitud failides |
git add fail | pane fail vahealale | edukal juhul sageli vaikne |
git diff --cached | vaata vaheala sisu | järgmisse versioonikirjesse minevad muudatused |
git commit -m '...' | loo versioonikirje | uue kirje lühikood ja kokkuvõte |
git log --oneline | vaata ajalugu | versioonikirjed ühe rea kaupa |
git restore fail | eemalda tööpuu muudatus | fail taastatakse vaheala seisu; salvestamata tööpuumuudatus kaob |
git restore --staged fail | eemalda fail vahealalt | sisu jääb alles, vaheala muutub |
git switch -c haru | loo ja ava uus haru | liigud uuele harule |
git pull --ff-only | uuenda puhas haru serverist | edasinihe (fast-forward) või selge keeldumine |
git push -u origin haru | saada haru GitHubi | üleslaadimise kokkuvõte |
Tüüpilised algaja vead
- tehakse
git addenne, kui muudatus on üle vaadatud - arvatakse, et
git diffnäitab ka täiesti uusi ehk jälgimata faile - aetakse segi tööpuu, vaheala ja versioonikirje
- tehakse
git pullmäärdunud tööpuuga - töötatakse otse
mainharus, kuigi muudatus võiks olla eraldi harus - kasutatakse
git push --forceilma aru saamata, kelle ajalugu see muudab
Kolm olekut: tööpuu, vaheala ja versioonikirje
Giti õppimine läheb palju lihtsamaks, kui eristad kolme kohta.
| Koht | Tähendus | Kontrollkäsk |
|---|---|---|
| tööpuu | sinu failid praegu kettal | git status, git diff |
| vaheala | järgmise versioonikirje ettevalmistus | git diff --cached |
versioonikirje (commit) | salvestatud loogiline muutus | git 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 statusnäitab, kas tööpuu on puhasgit pull --ff-onlyuuendab põhiharu ainult siis, kui seda saab teha edasinihkenagit switch -c parandushoiab muudatuse eraldi harusgit diffjagit diff --cachedvä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:
mainon 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 branchnäitab harusid; tärn näitab praegust harugit switch -c nimiloob uue haru ja liigub sinnagit switch mainliigub olemasolevale harulegit branch -d nimikustutab 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.
| Tegevus | Mõte | Millal kasutada |
|---|---|---|
merge | säilitab mõlema haru ajaloo | valmis haru ühendamisel |
rebase | tõstab sinu versioonikirjed teise haru lõppu | oma 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
rebaseharus, millele teised juba oma tööd rajavad, kui see ei ole kokku lepitud - ühise
mainharu 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:
<<<<<<< HEADall on sinu praeguse haru versioon=======eraldab kaks varianti>>>>>>> origin/mainall 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:
- ava fail redaktoris
- tee valmis õige lõpptekst
- kustuta konfliktimärgid
- kontrolli faili sisu
- 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 --hardgit clean -fdgit push --forcegit branch -D haru
Rahulikum kontrolljärjekord on:
git statusgit diffgit diff --cached- 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:
issueehk probleemikirje on ülesanne, viga või aruteluteemapull requestehk tõmbekutse esitab muudatusettepaneku ülevaatamiseks ja ühendamiseksreviewehk koodiülevaatus on teiste tagasiside tõmbekutse kohtachecklistehk 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:
- vali probleemikirje või kirjuta probleem lühidalt lahti
- loo selle jaoks haru, näiteks
fix-cat-less - tee väike loogiline muudatus
- loo selge sõnumiga versioonikirje
- saada haru käsuga
git pushGitHubi - ava tõmbekutse (
pull request) - vasta ülevaatuskommentaaridele uute versioonikirjetega
- 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
- Selgita, mis vahe on tööpuul, vahealal ja
commit-kirjel ehk versioonikirjel. - Miks ei näita
git diffuue jälgimata faili sisu? - Millal vaatad
git diff --cached? - Miks on
git switch -c parandusalgajale selgem kuigit checkout -b parandus? - Mis vahe on
git fetchjagit pull --ff-onlyvahel? - Millal kasutaksid
git restore --staged fail.txt? - 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 seisgit diffmuutused tööpuusgit diff --cachedmuutused vahealalgit add fail.txtlisa vahealalegit commit -m '...'loo versioonikirjegit switch -c parandusloo harugit pull --ff-onlyuuenda puhtaltgit push -u origin parandussaada harugit restore --staged fail.txteemalda vahealalt
Olulisemad lipud, märgid ja kiirnupud
HEADpraegune tippmainpõhiridaoriginkaugrepovahealajärgmise versioonikirje sisu