Archive

Archive for February, 2010

Git početnica, 4. dio – rješavanje konflikata

February 23rd, 2010 Senko Comments off

U prošlom postu u Git serijalu spomenuli smo mogućnost konflikata prilikom rebaziranja ili spajanja grana te dali par sugestija kako ih izbjeći. No kod kompliciranijih projekata i workflowova konflikti su ponekad neizbježni, stoga je korisno znati kako riješiti konflikt kad do njega dođe.

Rješavanje konflikata

Ukoliko sami radite na projektu, konflikti vam se vjerojatno neće događati (osim ukoliko ne pazite). No, ukoliko radite na projektu sa više ljudi, može vam se zadesiti da se nađete u situaciji gdje ćete morati riješiti konflikt.

Recimo da je naš helloworld projekt dobio na važnosti i sada na njemu rade dva developera, Mirko i Slavko. Mirko i Slavko u stvarnom životu radit će na svojim granama u svojim klonovima repozitorija, ali da si ovdje pojednostavnimo priču, svaki će imati po jednu granu u našem zajedničkom repozitoriju.

Kreirajmo obje grane, bez prebacivanja u njih:

> git checkout master
Switched to branch 'master'

> git branch mirko
> git branch slavko
> git branch -l
  helloworld-0
* master
  mirko
  slavko

Dolazi Mirko, vidi problem u načinu kako je definirana funkcija main i popravlja ga u svojoj grani:

> git checkout mirko
Switched to branch 'mirko'

[...promjene hello.c...]

> git diff
diff --git a/hello.c b/hello.c
index 0bb4941..8b08068 100644
--- a/hello.c
+++ b/hello.c
@@ -1,6 +1,7 @@
 #include <stdio.h>

-int main(void)
+int
+main(int argc, char *argv[])
 {
   printf("Hello world\n");
   return 0;

> git commit -a -m "popravio main prototip"
[mirko 4e5f904] popravio main prototip
 1 files changed, 2 insertions(+), 1 deletions(-)

U međuvremenu, dolazi Slavko, vidi isti problem, ne zna da je Mirko radio na istoj stvari pa ga rješava kod sebe:

> git checkout slavko
Switched to branch 'slavko'

[...promjene hello.c...]

> git diff
diff --git a/hello.c b/hello.c
index 0bb4941..38586b0 100644
--- a/hello.c
+++ b/hello.c
@@ -1,6 +1,6 @@
 #include <stdio.h>

-int main(void)
+int main(int argc, char **argv)
 {
   printf("Hello world\n");
   return 0;

> git commit -a -m "prepravio definiciju funkcije main"
[slavko 4bb59be] prepravio definiciju funkcije main
 1 files changed, 1 insertions(+), 1 deletions(-)

Sve je dobro dok su promjene u zasebnim granama. No u jednom trenu ćemo željeti sve Mirkove i Slavkove promjene spojiti u master. Prva promjena će proći dobro, no na drugoj će nam se dogoditi konflikt.

> git checkout master
Switched to branch 'master'

> git merge mirko
git merge mirko
Updating 302ef80..4e5f904
Fast-forward
 hello.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

> git merge slavko
git merge slavko
Auto-merging hello.c
CONFLICT (content): Merge conflict in hello.c
Automatic merge failed; fix conflicts and then commit the result.

Uh, huh… obojica su mijenjala isto mjesto u istoj datoteci, i git ne zna kako riješiti problem. Zbog toga je merge pauziran i dana nam je prilika da riješimo konflikt. Pogledajmo što se dogodilo:

git diff
diff --cc hello.c
index 8b08068,38586b0..0000000
--- a/hello.c
+++ b/hello.c
@@@ -1,7 -1,6 +1,11 @@@
  #include <stdio.h>

++<<<<<<< HEAD
 +int
 +main(int argc, char *argv[])
++=======
+ int main(int argc, char **argv)
++>>>>>>> slavko
  {
    printf("Hello world\n");
    return 0;

> cat hello.c
#include <stdio.h>

<<<<<<< HEAD
int
main(int argc, char *argv[])
=======
int main(int argc, char **argv)
>>>>>>> slavko
{
  printf("Hello world\n");
  return 0;
}

Diff prikazuje obje nekompatibilne promjene. Prva je iz trenutne grane (odnosno to je ona Mirkova promjena koju smo uspješno preuzeli spajanjem Mirkove grane), dok je druga iz grane slavko. Rješimo konflikt modificiranjem tog dijela datoteke da izgleda onako kako mi želimo:

[...promjene hello.c...]
cat hello.c
#include <stdio.h>

int
main(int argc, char **argv)
{
  printf("Hello world\n");
  return 0;
}

> git diff
diff --cc hello.c
index 8b08068,38586b0..0000000
--- a/hello.c
+++ b/hello.c
@@@ -1,7 -1,6 +1,7 @@@
  #include <<tdio.h>

 -int main(int argc, char **argv)
 +int
- main(int argc, char *argv[])
++main(int argc, char **argv)
  {
    printf("Hello world\n");
    return 0;

> git add hello.c
> git commit
[master fd96bab] Merge branch 'slavko'

Diff prikaz u slučaju konflikata je pomalo zbunjujuć, no snalaženje u samoj datoteci koju treba popraviti je relativno jednostavno - konflikt je između <<<<<<< i >>>>>>>, a ======= razdvaja konfliktne promjene.

Konflikt prilikom rebaziranja

Kao što smo već prije vidjeli, obično želimo grane održavati tako da u svakom trenu njihove promjene budu primjenjive na master (odnosno na baznu granu gdje ih na kraju želimo spojiti), a jedan od razloga je upravo izbjegavanje konflikata kod spajanja.

Jedan od razloga zbog kojih je konflikt kod spajanja nezgodan je i činjenica da problem praktički "prebacujemo" onom tko radi merge, a kod većih projekata to je obično osoba koja održava projekt (tj. glavni developer). Ukoliko od nje tražite da granu sa vašim promjenama spaja sa masterom, a to izaziva konflikte kod mergea, zapravo ste prilično nepristojni.

Zato je bolje prije nego zatražite (ili krenete raditi) spajanje rebazirati svoju granu tako da samo spajanje bude čisto. To znači da ćete eventualne konflikte morati sami rješiti prilikom rebaziranja.

Vratimo se malo u prošlost i zaboravimo da smo radili merge Mirkove i Slavkove grane:

> git reset --hard 302ef80039bd55fbbc680d84e37e5ebcf7f63a5c
HEAD is now at 302ef80 dodan README

Mirko odluči spojiti svoju granu s masterom. Njegovu granu nije potrebno rebazirati jer se nastavlja na master (tj master nema nikakvih novih promjena):

> git merge mirko
Updating 302ef80..4e5f904
Fast-forward
 hello.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

Slavko odluči spojiti svoju granu. Njegovu granu je potrebno rebazirati jer
master ima novih comittova:

> git checkout slavko
Switched to branch 'slavko'

> git rebase master
First, rewinding head to replay your work on top of it...
Applying: prepravio definiciju funkcije main
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.c
CONFLICT (content): Merge conflict in hello.c
Failed to merge in the changes.
Patch failed at 0001 prepravio definiciju funkcije main

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

Ovo izgleda mnogo strašnije nego poruka kod mergea! Ali problem je isti, u što se možemo uvjeriti pomoću git diff (s tim da će umjesto imena naše grane biti naziv commita u našoj grani s kojim ima problema). Nakon što napravimo ispravke u datoteci, trebamo nastaviti proces rebaziranja:

[...promjene hello.c...]
> git add hello.c
> git rebase --continue
Applying: prepravio definiciju funkcije main

Ovdje nismo ručno radili git commit, nego smo nakon popravka nastavili proces rebaziranja. Kako rebaziranje ide commit po commit, ukoliko ima još konflikata u narednim commitovima, rebase bi se opet zaustavio i zatražio da popravimo stvari.

Ukoliko zaključimo da je commit nepotreban (npr. zato što je u drugoj grani taj problem već riješen), možemo ga odbaciti. Ako se radi o ozbiljnom problemu za kojeg ne znamo kako ga riješiti, možemo prekinuti rebase, a grana će nam se vratiti u prvobitno stanje. U tom slučaju ćemo vjerojatno morati rješavati merge konflikte prilikom spajanja i napraviti merge a ne rebase.

Categories: Uncategorized Tags:

If Linus was starting a kernel in 2010…

February 10th, 2010 Senko Comments off

Imagine you’ve seen a blog post titled Free linux-like kernel sources for x86-64 PC’s with the following contents:

Do you pine for the nice days of linux 2.4, when men were men and wrote
their own device drivers? Are you without a nice project and just dying
to cut your teeth on a OS you can try to modify for your needs? Are you
finding it frustrating when everything works on linux? No more all-
nighters to get a nifty program working? Then this post might be just
for you :-)

As I tweeted a month(?) ago, I’m working on a free version of a
linux-lookalike for x86-64 computers. It has finally reached the stage
where it’s even usable (though may not be depending on what you want),
and I am willing to put out the sources for wider distribution. It is
just version 0.02 (+1 (very small) patch already), but I’ve successfully
run bash/gcc/gnu-make/gnu-sed/compress etc under it.

Sources for this pet project of mine can be found on github. The repo also
contains some README-file and a couple of binaries to work under it
(bash, update and gcc, what more can you ask for :-). Full kernel
source is provided, as no linux code has been used. Library sources are
only partially free, so that cannot be distributed currently. The
system is able to compile “as-is” and has been known to work. Heh.
Sources to the binaries (bash and gcc) can be found at the same place.

ALERT! WARNING! NOTE! These sources still need linux to be compiled
(and gcc, possibly gcc4, haven’t tested), and you need linux to
set it up if you want to run it, so it is not yet a standalone system
for those of you without linux. I’m working on it. You also need to be
something of a hacker to set it up (?), so for those hoping for an
alternative to linux, please ignore me. It is currently meant for
hackers interested in operating systems and x86-64′s with access to linux.

The system needs an IDE harddisk (sorry) and any VGA card. If
you are still interested, please read my blog post about it, and/or ask me
on Twitter for additinal info.

I can (well, almost) hear you asking yourselves “why?”. Next year (or the
one after it who knows) will be The Year Of Linux Desktop, and I’ve already got
Ubuntu. This is a program for hackers by a hacker. I’ve enjouyed doing
it, and somebody might enjoy looking at it and even modifying it for
their own needs. It is still small enough to understand, use and
modify, and I’m looking forward to any comments you might have.

Does this sound familiar to you? If you know your Linux history, is should – it’s a ripoff of the original Linux announcement post that Linus posted to the comp.os.minix newsgroup.

A few points to consider:

  • look what a crazy (in a positive way) guy’s hobby did to the computer industry
  • is kernel programming still fun? should it be? is it serious work now?
  • is there still fun to be had in non-web related stuff?
Categories: English Tags:

Git početnica, 3. dio – rukovanje promjenama

February 9th, 2010 Senko Comments off

Nakon što smo u prošlom postu proučili kako raditi grananje, spajanje i rebaziranje grana, git nam već može biti poprilično koristan alat. Kako projekt raste, git nam može pomoći da ne izgubimo glavu u različitim granama i verzijama koje održavamo unutar jednog projekta.

Interaktivno dodavanje promjena

Prilikom rada na projektu, često ćemo da bi stvar uopće natjerali da radi morati napraviti nekoliko nezavisnih promjena, a tek onda biti sigurni da smo dobili dobar rezultat. Obično tek tada želimo napraviti commit, ali bismo htjeli da nezavisne promjene idu u nezavisne commitove. Ako se te promjene nalaze u istoj datoteci, običan git add nam ne pomaže jer bi on označio cijelu datoteku za commit.

U tom slučaju možemo koristiti interaktivno dodavanje. Ono nam pruža veću kontrolu nad time što dodajemo u commit, a i preglednije je (i pruža nam priliku za review napravljenoga prije commitanja), pa preporučam da ga uvijek koristite, čak i kad želite dodati sve promjene.

Recimo da smo napravili dvije nezavisne izmjene u hello.c. datoteci i želimo ih committati odvojeno (primjer radim u novoj test grani koju ću kasnije obrisati):

> git checkout -b test
Switched to a new branch 'test'

> git diff
diff --git a/hello.c b/hello.c
index 0bb4941..d560074 100644
--- a/hello.c
+++ b/hello.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
 #include <stdio.h>

 int main(void)
@@ -5,3 +6,9 @@ int main(void)
   printf("Hello world\n");
   return 0;
 }
+
+void unused(void)
+{
+  puts("I'm never used");
+}
+

> git add -p
diff --git a/hello.c b/hello.c
index 0bb4941..d560074 100644
--- a/hello.c
+++ b/hello.c
@@ -1,3 +1,4 @@
+#include 
 #include 

 int main(void)
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y
@@ -5,3 +6,9 @@ int main(void)
   printf("Hello world\n");
   return 0;
 }
+
+void unused(void)
+{
+  puts("I'm never used");
+}
+
Stage this hunk [y,n,q,a,d,/,K,g,e,?]? n

Ovo će označiti (tj. spremiti u index) samo prvu promjenu u datoteci za committanje. To možemo provjeriti sa git diff --cached:

git diff --cached
diff --git a/hello.c b/hello.c
index 0bb4941..c6efc61 100644
--- a/hello.c
+++ b/hello.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
 #include <stdio.h>

 int main(void)

Pregled promjena u datotekama

Nakon što neko vrijeme radite na projektu, većina datoteka unutar projekta
vjerojatno će biti mijenjana mnogo puta. Kako bi vidjeli koje promjene smo radili
nad jednom datotekom (ili direktorijem), možemo koristiti još jedan oblik
već poznate git log naredbe:

> git log hello.c
commit 5e547517e1a29a08b3594f6b8c8c0a289070376d
Author: Senko Rasic <senko@localhost>
Date:   Sat Jan 23 06:31:05 2010 +0100
popravljen kod

commit 04f3667425705d29f2c3a10bb45e79f5cc6b7d7d
Author: Senko Rasic <senko@localhost>
Date:   Sat Jan 23 05:49:59 2010 +0100
malo uljepsano

commit 6e70237aaa84a0c8ff74bd0fad6cccb4d118b695
Author: Senko Rasic <senko@localhost>
Date:   Sat Jan 23 05:49:03 2010 +0100
prva verzija

Ovaj ispis dobar je ako želimo kronološki pregled promjena. No često je slučaj
da nas zanima zašto je baš neki dio (trenutne) datoteke napisan tako je, tj. koji
je razlog za dodavanje (ili promjenu) pojedine linije unutar koda.

Pregled promjena po pojedinim linijama datoteke omogućuje nam git blame,
tako nazvan jer nam govori tko je odgovoran za pojedinu liniju datoteke i zašto:

> git blame hello.c
5e547517 (Senko Rasic 2010-01-23 06:31:05 +0100 1) #include <stdio.h>
5e547517 (Senko Rasic 2010-01-23 06:31:05 +0100 2)
5e547517 (Senko Rasic 2010-01-23 06:31:05 +0100 3) int main(void)
04f36674 (Senko Rasic 2010-01-23 05:49:59 +0100 4) {
04f36674 (Senko Rasic 2010-01-23 05:49:59 +0100 5)   printf("Hello world\n");
5e547517 (Senko Rasic 2010-01-23 06:31:05 +0100 6)   return 0;
04f36674 (Senko Rasic 2010-01-23 05:49:59 +0100 7) }

Popis za svaku liniju sadrži skraćeni ID commita, autora te datum promjene.
Nakon što identificiramo promjenu koja nas zanima, pomoću već poznate
git show naredbe možemo vidjeti i ostale detalje te promjene.

Označavanje (tagiranje) commitova

Naš “Hello World” projekt već ima praktički svu funkcionalnost koju želimo,
stoga je pravo vrijeme da napravimo naš prvi release. Osim što možemo napraviti
arhivu izvornog koda (kao tar.gz ili u nekom drugom formatu) i poslati je korisnicima
svog programa, korisno je i u samom repozitoriju označiti da smo napravili
release.

Kako bismo “zapamtili” da smo napravili release, možemo dodati oznaku (tag) na
trenutni commit. Kako svaki commit zna za sve koji su se dogodili prije njega,
ta oznaka poslužit će nam da bi na jednostavan način dolazili do stanja projekta
u raznim fazama razvoja, bez da pamtimo IDeve comittova.

Oznaka (tj. tag) je (pojednostavljeno) najobičniji “alias” na ID commita.
Postavljenu oznaku možemo koristiti praktički svugdje gdje moramo navoditi ID
commita. Možemo ga koristiti kako god želimo – najčešća praksa je obilježavanje
kad se dogodilo nešto značajno u projektu, kao što je release.

Tagirajmo release 0.1 našeg projekta. Kako release radimo iz master
grane, pripazit ćemo ne tagiramo commit u krivoj grani:

> git checkout master
> git tag -m "postavljamo tag" "helloworld-0.1"

tagove možemo pregledavati pomoću git tag -l, a brisati pomoću
git tag -d <ime_taga>.

Prilikom postavljanja oznake, možemo je i kriptografski potpisati (gpg-om,
uz korištenje gpg privatnog ključa za mail adresu koju koristimo kod rada
s repozitorijem), korištenjem opcije -s.

Sretni sa napravljenim releasom, krećemo dalje sa razvojem projekta. Verzija
0.1 je potpun program, ali mu nedostaje build sustav, zbog čega svaki put moramo
ručno pozivati kompilator. Namjera nam je to riješiti korištenjem make
alata.

Kreirajmo konfiguracijsku datoteku za make zvanu Makefile
(napomena: make je izbirljiv glede sintakse, stoga je bitno na određenim mjestima
koristiti tab umjesto razmaka, što je posebno naznačeno u ovom listingu):

CC = gcc
OBJS = hello.o
CFLAGS = -Wall -Werror -O3 -g

.PHONY: all clean

all: hello

hello: $(OBJS)
<tab>$(CC) $(OBJS) -o $@

%.o: %.c
<tab>$(CC) $(CFLAGS) -c $< -o $@

clean:
<tab>rm -f hello $(OBJS)

Dodajmo novostvorenu datoteku u projekt, repozicionirajmo doc granu
(pošto imamo novosti u masteru) i spojimo je natrag u master granu.
Pošto smo završili sa doc granom, na kraju je možemo i obrisati.

> git add Makefile
> git commit -m "dodan Makefile"
master b23a04b] dodan Makefile
 1 files changed, 17 insertions(+), 0 deletions(-)
 create mode 100644 Makefile

> git checkout doc
Switched to branch 'doc'

> git rebase master
First, rewinding head to replay your work on top of it...
Applying: dodan README

> git checkout master
Switched to branch 'master'

> git merge doc
Updating b23a04b..302ef80
Fast-forward
 README.txt |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 README.txt

> git branch -d doc
Deleted branch doc (was 302ef80).

Pregršt novih promjena! Pogledajmo što smo sve izmjenili od zadnjeg releasea:

< git log helloworld-0.1..HEAD
commit 302ef80039bd55fbbc680d84e37e5ebcf7f63a5c
Author: Senko Rasic <senko@localhost>
Date:   Sat Jan 23 06:06:26 2010 +0100
dodan README

commit b23a04b47dbc1044d44d94ee0a5df967f8f1b26d
Author: Senko Rasic <senko@localhost>
Date:   Fri Feb 5 16:02:54 2010 +0100
dodan Makefile

Poput grana, tagove je moguće checkout-ati, čime se vraćamo u prošlost,
u stanje projekta kakvo je bilo u trenutku tagiranja. Vratimo se malo u prošlost
do naše verzije 0.1:

> git checkout helloworld-0.1
Note: moving to 'helloworld-0.1' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
  git checkout -b 
HEAD is now at 5e54751... popravljen kod

Git nas upozorava da smo došli na commit koji nije zadnji u nekoj grani. Ukoliko
želimo raditi bilo kakve modifikacije na projektu od ove točke, moramo kreirati novu
granu u koju će one biti spremljene.

Razvojne i stabilne grane

Ovo nam daje dobru ideju - možemo kreirati novu granu s početkom u helloworld-0.1,
koja služi samo za "održavanje" postojećeg koda i ispravljanje pogrešaka, dok ćemo sav
novi razvoj na projektu raditi kao i do sada na masteru. Ovime se želimo
osigurati da imamo "stabilnu verziju" projekta u koju nam neće slučajno upadati i
nove stvari koje razvijamo na "razvojnoj verziji" projekta na master grani.

> git checkout -b helloworld-0 helloworld-0.1
Switched to a new branch 'helloworld-0'

Grana helloworld-0 sadrži commit tagiran sa 'helloworld-0.1' i
sve njegove prethodnike i predstavlja stanje projekta kakvo je bilo u trenutku
kada smo tagirali taj commit. Granu potom možemo koristiti samo za promjene na
stabilnoj/releasanoj verziji, dok nam master ostaje za novi razvoj.

Cherry-picking

Ponekad prilikom rada na novoj verziji uočimo i ispravimo pogrešku koja postoji
i u već releasanoj verziji. Iako bismo ispravke mogli napraviti posebno na obje
grane, jednostavnije je ispravak napraviti na jednoj (obično razvojnoj, tj.
masteru) i nakon toga istu zakrpu primjeniti i na drugu. Ukoliko ispravku radimo
na masteru, primjenjivanje zakrpe i na starije release grane se zove
backporting.

Da bismo napravili backport commita koji ispravlja neku grešku, ne možemo
koristiti niti merge niti rebase, jer oni preuzimaju sve commitove iz mastera.
U slučaju kada želimo izabrati samo jedan commit (ili nekoliko njih, ali ne
cijelu granu) iz jedne grane i primjeniti ga na drugu, možemo koristiti
git cherry-pick.

Korisnici verzije 0.1 našeg softvera su ogorčeni jer ručno moraju pokretati
gcc. Smatraju da je to bug, a kako mi već imamo rješenje u obliku Makefilea
u master grani, rješenje je jednostavno - backportati commit koji je dodao
Makefile i napraviti novi release na 0.* grani.

> git cherry-pick b23a04b47dbc1044d44d94ee0a5df967f8f1b26d
Finished one cherry-pick.
[helloworld-0 f60bcbd] dodan Makefile
 1 files changed, 17 insertions(+), 0 deletions(-)
 create mode 100644 Makefile

Traženi commit je preuzet u trenutnu granu. Preciznije, promjene
koje je traženi commit napravio su napravljene i spremljene i za trenutnu granu.
Ovo je bitno zbog toga što se ID commita mijenja - kao i kod rebasea, originalni
i cherry-pickani commitovi nisu isti. Ovisno o daljnjim promjenama koje radimo
na grani, možemo se naći u situaciji da granu više nije moguće rebazirati ili
spojiti sa masterom, odnosno trebali bi rješavati konflikte. Stoga bi trebalo
izbjegavati cherry-picking iz grane koju u budućnosti želimo spojiti sa trenutnom
granom.

Više o konfliktima te što napraviti kad vam se oni dogode pročitajte u slijedećem postu u ovom serijalu, za par dana...

Categories: Uncategorized Tags:

Tjedan konferencija

February 4th, 2010 Senko 2 comments

FOSDEM

Ovaj vikend se u Bruxellesu održava tradicionalna FOSDEM konferencija. Broj zanimljivih predavanja i prezentacija je ogroman (samo popis stvari koje bih želio poslušati zahtjeva da se kloniram par puta :), a osim toga bit će velik broj zanimljivih ljudi koji se bave različitim stvarima, štandova, … a ne smijemo zaboraviti niti belgijsku pivu :) Tako da mi je drago da ću i ove godine prisustvovati ovoj konferenciji.

I'm going to FOSDEM, the Free and Open Source Software Developers' European Meeting

Računajte na #fosdem tweetove (po uvjetom da gomile geekova ne preopterete wireless, što je obično slučaj :) te kasnije i blog post o stvarima koje su se meni osobno isticale na konfi.

IT Showoff

Slijedeći petak će se u prostoru FERa u Zagrebu održati prvi jubilarni IT Showoff, na kojem ću održati prezentaciju i demo o tome kako i zašto koristiti git. Sa sobom ću imati i N900 i laptop sa složenom razvojnom okolinom za Maemo, pa mi se slobodno javite ukoliko želite popričati o Maemu, N900 te razvoju softvera za ovaj sustav.

IT Showoff

N900 na eHrvatska TV

Kad smo već kod N900, nedavno je ekipa iz eHrvatska TV napravila reportažu o ovom uređaju, Maemou i Linuxu u sklopu koje su i mene priupitali za par pitanja. Snimku reportaže možete pogledati na eHrvatska kanalu na YouTube-u.

Categories: Uncategorized Tags: