Versionhallintajärjestelmä on sovellus, joka tallentaa ja hallitsee ohjelmistoprojektin eri versioita. Sen keskeisiä ominaisuuksia ja hyötyjä ovat mm.:
Käytännössä versionhallinta on välttämätön työkalu ammattimaisessa ohjelmistokehityksessä. Sitä käyttävät kaikenkokoiset organisaatiot ja tiimit varmistaakseen tehokkaan projektinhallinnan.
Versionhallintajärjestelmiä on useita, joista tunnetuimpia ovat Git, Subversion ja Mercurial. Näistä Git on nykyään yleisin ja laajimmin käytetty, ja siksi keskitymme tässä osiossa pääosin sen käyttöön ja toimintaperiaatteisiin, vaikka monet konseptit ovat samankaltaisia myös muissa työkaluissa.
Käytännössä versionhallinta voidaan nähdä ohjelmiston kehityksen aikajanana, johon tallennetaan kaikkialle koodiin tehtyjä muutoksia sopivin väliajoin.
gitGraph
commit id: "1. tallennuspiste - aloitus"
commit id: "2. commit - uusi ominaisuus"
commit id: "kolmas versio"
commit id: "virhe korjattu"
commit id: "uusi ominaisuus lisätty"
Tallennuspisteitä kutsutaan nimillä “commit”, “revision” tai “version” hieman järjestelmästä riippuen. Aikajanaa kutsutaan taas usein kehityshaaraksi (branch), koska haaroja voi olla päähaaran (tässä “main”) lisäksi useita muitakin.
Kansiota, johon kaikki työtiedostot, niiden versiot, haarat ja muut versionhallinnan metatiedot on tallennettu, kutsutaan tietovarastoksi tai yleisemmin puhekielessä repositorioksi.
Seuraavassa kaaviossa havainnollistetaan repositoriota, jossa on useampi rinnakkainen kehityshaara:
gitGraph
commit id: "initial commit"
commit id: "2. commit - uusi ominaisuus"
branch feature1
checkout feature1
commit id: "feature1: joku uusi ominaisuus"
checkout main
branch feature2
checkout feature2
commit id: "feature2: kolmas uusi ominaisuus"
checkout main
merge feature1
merge feature2
Tässä uusia ominaisuuksia on kehitetty yhteisen lähtökohdan (commit) pohjalle käyttäen rinnakkaisia toisistaan riippumattomia haaroja. Lopuksi kehitetyt ominaisuudet on liitetty takaisin osaksi pääkehityshaaraa. Tällöin pääkehityshaaran versiohistoriaan sisältyvät myös kaikki erillisissä kehityshaaroissa tehdyt muutokset (commit).
Tämän jälkeen kehityshaarat voitaisiin tarpeettomina poistaa, koska pääkehityshaara sisältää jo koko historian:
gitGraph
commit id: "initial commit"
commit id: "2. commit - uusi ominaisuus"
commit id: "feature1: joku uusi ominaisuus"
commit id: "feature2: kolmas uusi ominaisuus"
Haarojen yhteenliittämisestä käytetään termiä merge. Käytännössä uusia kehityshaaroja voi luoda minkä tahansa olemassa olevan haaran pohjalta, ja kehityshaaroja voi myös liittää toisiinsa vapaasti.
Jos yhteenliitettävissä haaroissa on muokattu samoja tiedostoja siten, että muutokset ovat keskenään ristiriidassa, syntyy konflikti (conflict). Tällöin kehittäjän, joka liittämisen tekee, täytyy käydä muutokset läpi ja ratkaista ristiriidat koodista “käsin” ennen kuin lopullinen yhteenliitetty versio voidaan tallentaa.
On huomionarvoista, että versionhallintatyökalu ei kykene itsenäisesti arvaamaan, miten ristiriidassa olevat muutokset tulisi yhdistää. Tämä voisi johtaa helposti virheisiin ohjelman toiminnassa.
Konfliktien ratkaisemisen helpottamiseksi löytyy monia osin automatisoituja työkaluja (merge tools), mutta viimeisimmästä muutoksesta on vastuussa haarojen liitokset tehnyt kehittäjä. Konfliktien syntyminen ja ratkominen on täysin luonnollinen osa ohjelmistokehityksen tiimityötä.
Aktiivista kehityshaaraa voi vaihtaa checkout-toiminnolla. Käytännössä tämä tarkoittaa sitä, että kun koodari vaihtaa toiseen kehityshaaraan, versionhallintatyökalu korvaa projektikansiossa olevat nykyiset työtiedostot valitun version tiedostoilla repositoriosta.
git - the stupid content tracker on virallisen nimensä mukaisesti kaikenlaisen sisällön muutosten seurantaan tarkoitettu avoimen lähdekoodin sovellus. Gitin avulla voi versioida kaikentyyppisiä tiedostoja, mutta kaikki ominaisuudet ovat käytössä vain tekstitiedostoja käsitellessä. Git-yhteisön ylläpitämät kotisivut opetusmateriaaleineen löytyvät osoitteesta https://git-scm.com/.
Alun perin sovelluksen kehittämisen aloitti vuonna 2005 Linus Torvalds Linux-käyttöjärjestelmän kehityksen tarpeisiin ja se on sittemmin noussut yleisesti käytetyksi versionhallintajärjestelmäksi, joka on suosittu niin pienissä kuin suurissakin ohjelmistokehitysprojekteissa.
Nimestään huolimatta sovellus on monipuolinen, tehokas ja tietoturvalliseksi suunniteltu. Sovelluksen hallinta saattaa alkuun tuntua haastavalta, mutta koska kyseessä on erittäin tärkeä osa ohjelmistokehittäjän työkalupakkia, sen opettelu palkitsee. Käytämme gitin perustoiminnallisuuksia tarpeen mukaan läpi opintojaksojen.
Git on hajautettu versionhallintajärjestelmä, mikä tarkoittaa, että jokaisella kehittäjällä on oma kopio koko projektin historiasta eli repositoriosta omalla koneellaan ja gittiä käytetään ensisijaisesti paikallisesti omalla koneella. Gitin avulla hallinnoitu projekti ei ole siis riippuvainen mistään keskuspalvelimesta, vaikka yleisesti repositoriota jaetaankin verkkopalveluiden, kuten GitHubin, välityksellä.
Lataus- ja asennusvaihtoehdot eri käyttöjärjestelmille
Gitin asentaminen ja käyttö omassa harjoitusprojektissa tehdään seuraavassa moduulissa.
Git on lähtökohtaisesti käyttöjärjestelmän komentoriviltä ajettava ohjelma, eli sitä käytetään käsin kirjoitettavilla tekstipohjaisilla komennoilla. Lisäksi löytyy monia gittiä käyttäviä graafisella käyttöliittymällä varustettuja työkaluja, ja git on integroitu myös käytännössä kaikkiin moderneihin IDEihin.
Komentorivin käyttö vaatii alkuun hieman perehtymistä, mutta auttaa ymmärtämään Gitin toimintaa syvällisemmin. Jos git-komentojen käyttö on hallussa, on myös graafisten työkalujen toiminnan ymmärtäminen ja käyttö loogisempaa.
Git-repositorio luodaan ajamalla git init -komento sen kansion sisällä, jossa koko ohjelmointiprojekti sijaitsee. Tämä voidaan tehdä myös koodieditorin työkalulla. Jatkossa git-komentoesimerkeissä oletetaan, että ne suoritetaan aina tässä samassa kansiossa.
Tämän jälkeen Gitin toiminnan perusperiaate on, että tiedostoilla on kolme eräänlaista tilaa tai paikkaa:
https://git-scm.com/book/en/v2/Getting-Started-What-is-Git
git init suoritettiin). Työtilassa olevat tiedostot voivat olla joko versionhallinnan seurannassa tai seurannan ulkopuolella (katso .gitignore alempaa)..git/-kansio).Käytännön työnkulku etenee yksinkertaisimmillaan seuraavasti:
git add joko tiedosto kerrallaan git add <tiedosto(tai lista)>, esimerkiksi git add main.py kissa.py tai vaikka koko kansio kerralla: git add ..
.git/-kansio) luomalla uuden tallennuspisteen commit-komennolla: git commit -m "commit-viesti". Commit-viestissä kuvataan mahdollisimman selkeästi, mitä muutoksia uusi tallennuspiste sisältää.Huom: Näet aina repositorion tilanteen git status -komennolla. Tätä voi käyttää vaikka jokaisen edellä mainitun komennon välissä, jotta näkee, mitä repositoriossa on tapahtumassa.
Jos kehittäjä ei halua muokata alkuperäistä koodia suoraan, vaan jatkaa kehittämistä säästäen alkuperäisen koodin versiohistorioineen koskemattomana, hän voi luoda rinnalle uuden kehityshaaran komennolla git branch, esim. git branch uusi-ominaisuus.
Luotu kehityshaara “uusi-ominaisuus” jakaa saman historian eli kaikki commitit pääkehityshaaran (main (tai master)) kanssa. Uuteen haaraan siirtyminen tapahtuu komennolla git checkout, esim. git checkout uusi-ominaisuus. Uuden haaran luomisen ja valitsemisen voi tehdä myös yhdellä komennolla git checkout -b uusi-ominaisuus.
Tämän jälkeen kaikki tehdyt commitit tallentuvat vain uuteen haaraan. Takaisin pääkehityshaaraan pääsee komennolla git checkout main, jolloin työtiedostot korvataan pääkehityshaaran viimeisimmän commitin tiedostoilla.
Kun kehityshaarassa kehitetty uusi ominaisuus on valmis, se voidaan liittää takaisin pääkehityshaaraan komennolla git merge, esim. git merge uusi-ominaisuus. Tällöin pääkehityshaaraan tallentuvat myös kaikki ne commitit, jotka on tehty uudessa haarassa.
Haaroja voidaan liittää toisiinsa ristiin rastiin vapaasti, ja git merge liittää valitun haaran siihen haaraan, joka on aktiivisena. Eli kun halutaan liittää uusi-ominaisuus päähaaraan main, kannattaa ensin varmistaa, että se on aktiivinen (git status tai git checkout main).
VS Code -editorissa haarojen luominen ja vaihtaminen onnistuu helposti myös vasemman alalaidan Git-työkalun kautta, eikä komentorivin käyttö ole välttämätöntä.

Erillisten kehityshaarojen luominen ei ole tällä opintojaksolla välttämätöntä, mutta harjoitteleminen jo tässä vaiheessa helpottaa tärkeän työkalun omaksumista tulevilla kursseilla.
Muita käteviä Git-komentoja ovat mm.:
git log: commit-historian tarkastelu (kuka, mitä, milloin), paina tarvittaessa ‘q’-näppäintä lopettaaksesi selaamisengit diff: muutosten vertailu, esimerkiksi työtilassa olevien tiedostojen ja repositoriossa olevien tiedostojen välillä, tai kahden commitin välillägit reset: staging arean tyhjentäminen, paluu aiempaan versioon, uusien muutosten hylkääminen, käytä harkiten!Git on todella monipuolinen työkalu ja tarpeellisia toimintoja voi ja kannattaa etsiä ja opetella tarpeen mukaan itsekin. Tällä jaksolla otetaan vain pintaraapaisu tärkeimpiin ominaisuuksiin.
.git/-kansioKun uusi repositorio luodaan (git init), syntyy projektikansioon alikansio .git/. Tämä sisältää käytännössä kaiken projektin versionhallintaan liittyvän tiedon. Kansio on niin sanottu piilotiedosto, joka ei oletusasetuksilla näy käyttöjärjestelmän eikä editorin tiedostoselaimessa. Jos kansion poistaa, tuhoutuu kaikki versionhallintaan liittyvä ja jäljelle jää vain sillä hetkellä kansiossa olevat työtiedostot. Kansion sisältöä ei saa myöskään muokata suoraan, vaan kaikki repositorion kanssa työskentely tapahtuu gitin eri komennoilla.
Esimerkiksi kehityshaaraa vaihdettaessa (git checkout <branchname>) git korvaa työtiedostot .git/-kansiosta valitun kehityshaaran tuoreimman tallennuspisteen tiedostoilla.
Eri git-työkaluja (komentorivi, editorin toiminnot, jne.) voi huoletta käyttää samassa projektissa rinnakkain, koska ne kaikki operoivat käsittelemällä tätä samaa kansiota.
.gitignore-tiedostoGit seuraa vain niitä tiedostoja, jotka on lisätty versionhallintaan. Tiedostot, joita ei haluta seurata, voidaan määritellä .gitignore-tiedostossa. Tämä on tekstitiedosto, joka sijaitsee yleensä projektikansion juuritasolla. Tiedostoon kirjoitetaan lista tiedostopolkuja tai tiedostonimiä, jotka halutaan jättää versionhallinnan ulkopuolelle.
Pääsääntöisesti versionhallinnan ulkopuolelle jätetään kaikki, mikä ei liity suoraan ohjelmakoodiin. Tällaisia tiedostoja ja kansioita ovat muun muassa:
.exe, .pyc), ja muut automaattisesti lähdekoodista generoituvat tiedostot.Esimerkiksi Python-projektissa on suositeltavaa jättää ainakin virtuaaliympäristön tiedostot versionhallinnan ulkopuolelle, jolloin .gitignore-tiedostoon lisätään rivi .venv/. Tyypillinen Python-projektin .gitignore voisi näyttää seuraavalta:
# Python cache files
__pycache__/
*.pyc
*.pyo
# Virtual environment
.venv/
# IDE settings
.vscode/
.idea/
# OS generated files
.DS_Store
Thumbs.db
* on niin sanottu jokerimerkki, joka tarkoittaa mitä tahansa merkkijonoa. Esimerkiksi *.pyc tarkoittaa kaikkia .pyc-päätteisiä tiedostoja.
Alle on poimittu muutamia hyödyllisiä linkkejä kiinnostuneille:
Seuraavaksi otetaan versionhallinta käyttöön omassa harjoitusprojektissa.