Lähdekoodin versionhallinta

Tällä kertaa aihe on hieman aiempaa käytännönläheisempi ja melko tekninen. Kerromme miten lähdekoodin versionhallinta hoidetaan innovaatiopalvelua toteutettaessa.

Versionhallintatyökaluksi on valittu Git, joka on Linus Torvaldsin kehittämä avoimen lähdekoodin hajautettu versionhallintaohjelmisto. Linus tarvitsi Linux käyttöjärjestelmän ytimen lähdekoodin versionhallintaan sopivan versionhallintaohjelmiston, mutta koska sellaista ei löytynyt, hän päätti koodata sellaisen itse. Omien sanojensa mukaan hän toteutti enimmäisen toimivan version Git:istä kahdessa viikossa.

Versionhallinta ohjelmistokehityksessä ei ole niin yksinkertainen asia kuin miltä se saattaa kuulostaa. Versiohallinnassa voidaan määrittää tietty versio ohjelmasta koostuvaksi tiettyjen tiedostojen tietyistä versiosta, ja kehittää eri versioita rinnan. Versionhallinnalla voidaan myös estää päällekkäisten muutosten, eli konfliktien syntyminen, silloin kun samaa sovellusta kehittää useampi ohjelmoija samaan aikaan. Hajautettu versionhallinta mahdollistaa myös paikasta riippumattoman työskentelyn. Jokainen sovelluskehittäjä voi kloonata koko versionhallintasäilön omalle koneelleen ja koodata vaikka kesämökillä ilman internetyhteyttä (vaikka tämä on mahdollista, niin kesämökillä pitää tietysti tehdä kaikkea muuta kuin koodata).

Ennen kuin versionhallinta voidaan ottaa käyttöön ohjelmistokehitysprojektissa, täytyy sopia metodit joiden mukaan versiohallintaa käytetään. Varsinkin git on niin joustava työkalu, että ilman yhteisesti sovittuja käytäntöjä sen käytöstä olisi todennäköisesti vain haittaa. Onneksi näitä ei tarvitse keksiä itse, vaan monet ovat ystävällisesti dokumentoineet omia käytäntöjään internettiin muiden saataville. Innovaatiopalvelumallin projekteissa käytämme tätä mallia:http://nvie.com/posts/a-successful-git-branching-model/

Tärkeintä ei ole käyttää parasta versionhallintakäytäntöä, vaan se, että käytetään edes jotain yhteisesti sovittua käytäntöä.



Esimerkki Git:in käytöstä sovitun käytännön mukaan Rails-sovelluksen kehityksessä

Esimerkki on melko pitkä, mutta se kattaa uuden Git-säilön luonnin, develop ja feature-haarojen luonnin, säilön kloonamisen käyttäjäkohtaisesti, muutosten tekemisen feature-haaroihin, ja niiden sulauttamisen (merge)  develop haaraan, sekä konfliktien ratkomisen.

Luodaan yhteinen git-säilö (origin), johon kaikki sovelluskehittäjät “työntävät” omat muutoksensa. Yhteinen säilö luodaan –bare-määritteellä, jolloin se ei sisällä lainkaan varsinaisia lähdekooditiedostoja, ainoastaan versiohistorian. Tällä estetään se, että kukaan ei mene vahigossa koodaamaan suoraan origin-sailöön, joka aiheuttaisi tarpeettomia ongelmia.

git init --bare project1.git
Initialized empty Git repository in /l/rails/project1.git/

Kloonataan se käyttäjäkohtaisesti

cd jsalmela
git clone ../project1.git
Initialized empty Git repository in /l/rails/jsalmela/project1/.git/
warning: You appear to have cloned an empty repository.
cd project1

Luodaan rails projekti

rails new .
git add .
git commit -a -m "projektin luonti"

Luodaan develop haara ja työnnetään muutokset originille

git checkout -b develop master
git push origin master
git push origin develop

Tämän jälkeen joku toinen voi kloonata säilön. Leikitään, että olen nyt toinen käyttäjä (käyttäjätunnus: jokumuu). Todellisuudessa voisin kloonata säilön vaikka eri koneelle, mutta tässä esimerkissä käytetään vain toista hakemistoa samalla palvelimella.

cd /l/rails/jokumuu
git clone ../project1.git
cd project1
ls
Gemfile  Gemfile.lock  README  Rakefile  app  config  config.ru  db  doc  lib  log public script  test  vendor

Luodaan lokaali develop-haara originin develop-haarasta

git checkout -b develop origin/develop
Branch develop set up to track remote branch develop from origin.
Switched to a new branch 'develop'

Nyt voidaan luoda uusi feature-haara develop-haarasta jossa voidaan alkaa koodaamaan.

Luodaan tietokanta ja home-controlleri.

git checkout -b feature1 develop
Switched to a new branch 'feature1'
rake db:create
rails generate controller home index

Sulautetaan develop -haaraan ja poistetaan feature-haara

git checkout develop
git merge --no-ff feature1
git branch -d feature1

Ja työnnetään muutokset origin-repoon

git push origin develop

Vaihdetaan käyttäjää (jsalmela)

cd /l/rails/jsalmela/project1
git branch -a
* develop
master
remotes/origin/develop
remotes/origin/master

Ollaan näköjään develop-haarassa, joten päivitetään se ajan tasalle originista

git pull origin develop

Luodaan uusi feature-haara (feature-haarat ovat lokaaleja, joten voidaan käyttää samaa nimeä kuin aiemmin)

git checkout -b feature1 develop

Koodataan: Luodaan tietokanta, muutetaan home/index näkymää, poistetaan oletussivu ja asetetaan oletusreitti osoittamaan home-controllerin index-toimintoon.

rake db:create
echo "<h1>Hello, Rails</h1>" > app/views/home/index.html.erb
rm public/index.html
vim config/routes.rb
------------------
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
root :to => 'home#index'
-------------------

käynnistetään sovellus

rails server

Testataan

<Ctrl-Z>
bg
curl localhost:3000
-----------
Started GET "/" for 127.0.0.1 at 2011-09-27 17:17:17 +0300
Processing by HomeController#index as */*
Rendered home/index.html.erb within layouts/application (0.4ms)
Completed 200 OK in 13ms (Views: 12.3ms | ActiveRecord: 0.0ms)
<!DOCTYPE html>
....
<body>
<h1>Hello, Rails</h1>
</body>
</html>
-------------

Toimii, pysäytetään sovellus

fg
<Ctrl-C>

Commit

git commit -a -m "muoks"

Jokumuu muokkaa myös index.html:ää

cd /l/rails/jokumuu/project1
git branch -a
* develop
f1
master
remotes/origin/HEAD -> origin/master
remotes/origin/develop
remotes/origin/master
git pull origin develop
From /l/rails/jokumuu/../project1
* branch            develop    -> FETCH_HEAD
Already up-to-date.
git checkout -b feature2 develop
Switched to a new branch 'feature2'
echo "<h1>Hello World</h1><p>test</p>" > app/views/home/index.html.erb
git commit -a -m "index.html muokattu"
git checkout develop
git pull origin develop
git merge --no-ff feature2
git branch -d feature2
git push origin develop

Jsalmela yrittää nyt päivittää omia muutoksiaan originille

cd /l/rails/jsalmela/project1
git checkout develop
git pull origin develop

Saadaan aikaiseksi konflikti

git merge --no-ff feature1
Auto-merging app/views/home/index.html.erb
CONFLICT (content): Merge conflict in app/views/home/index.html.erb
Removing public/index.html
Automatic merge failed; fix conflicts and then commit the result.
[1] 10652 exit 1 git merge --no-ff feature1

korjataan se

vim app/views/home/index.html.erb

Tiedosto näyttää tältä:

<<<<<<< HEAD
<h1>Hello World</h1><p>test</p>
=======
<h1>Hello, Rails</h1>
>>>>>>> feature1
~

Muokataan:

<h1>Hello Rails</h1><p>test</p>

Konflikti ratkottu

git add app/views/home/index.html.erb
git commit -a -m "konflikti ratkottu app/views/home/index.html.erb"

Voidaan päivittää originiin

git push origin develop