Sdílené repozitáře verzovacího systému GIT (git, gitweb, gitosis)

Při práci na projektech jako je vývoj aplikací, vytváření dokumentace atd. je dobré mít přehled provedených změn a celkového stavu projektu. To umožňuji systémy pro správu verzí. Slyšet je v současnosti nejvíce o systémech SVN, GIT, CVS, Mercurial a Bazaar. Systémy jsou centralizované (SVN, CVS) nebo distribuované (GIT, Mercurial, Bazaar). V případě centralizovaných systémů všichni uživatelé pracují s jedním sdíleným repozitářem zatímco u distribuovaných si každý uživatel vytváří vlastní lokální kopii sdíleného repozitáře se kterou pracuje. Každý má své výhody i nevýhody, výběr vhodného systému zůstává na Vás. V tomto článku se zaměřím na verzovací systém GIT a konfiguraci jeho sdílených repozitářů. GIT je poměrně nový systém, na jeho vývoji začal pracovat Linus Torvalds s jediným účelem – ulehčit správu vývoje linuxového kernelu. Postupně se však rozšířil a v současnosti jej používají pro svůj vývoj například Yahoo, Facebook, Twitter, jQuery, 37 signals a mnoho dalších.

Při práci s GIT repozitáři většinou potřebujeme zajistit jejich zpřístupnění více uživatelům.
V takové situaci nám nezbývá nic jiného, než vytvořit sdílený GIT repozitář, ke kterému budou
mít tito uživatelé přístup. Pro zpřístupnění takového repozitáře musíme nejprve provést
potřebnou konfiguraci na straně serveru. Jak lze taková konfigurace provést si ukážeme zde.

Mějme 3 uživatele: user1, user2 a user3. user1 a user2 mají mít k repozitáři práva čtení i
zápisu zatímco user3 pouze práva ke čtení. Všichni tři uživatelé si přejí mít možnost prohlížet obsah repozitáře
také přímo v internetovém prohlížeči. Server na kterém se bude nacházet sdílený repozitář
nazveme gitserver. Graficky znázorněné zadání vypadá takto:

Začneme vytvořením uživatele s názvem „git“, prostřednictvím něhož uživatelé budou moci přistupovat
k repozitáři. Pokud zatím nemáme na našem lokálním PC vygenerovaný vlastní SSH klíč, vygenerujeme jej:

[localhost:~]$ ssh-keygen -t dsa

Veřejný SSH klíč nahrajeme na server:

[localhost:~]$ scp ~/.ssh/id_dsa.pub root@gitserver:/tmp

A přes SSH se na server přihlásíme:

[localhost:~]$ ssh root@gitserver

Na serveru vytvoříme uživatele „git“ s domácím adresářem v cestě /home/git/:

[gitserver:/]$ useradd -d /home/git git

Do souboru /home/git/.ssh/authorized_keys vložíme náš SSH klíč:

[gitserver:/]$ cat /tmp/id_dsa.pub > /home/git/.ssh/autorized_keys

Nyní se odhlásíme ze serveru a vyzkoušíme se k němu přihlásit pod uživatelem git:

[localhost:~]$ ssh git@gitserver

Pokud je vše nastaveno správně, přihlášení proběhne bez potřeby zadání přístupového hesla. Nyní musíme na server nainstalovat
potřebné balíčky GITu. Přihlásíme se tedy opět pod superuživatelem a stáhneme balíčky git a git-core:

[gitserver:/]$ ssh root@gitserver
[gitserver:/]$ yum install git git-core

Repozitáře budeme udržovat v adresáři /home/git/repositories. V domovském adresáři uživatele git tedy vytvoříme adresář repositories a v něm adresář projekt.git, což bude náš první sdílený GIT repozitář:

[gitserver:/]$ mkdir /home/git/repositories
[gitserver:/]$ mkdir /home/git/repositories/projekt.git

Stejně jako lokální GIT repozitář musíme i ten sdílený nejdříve inicializovat. Příkazem git init však vytvoříme i pracovní adresář, který u sdíleného repozitáře nepotřebujeme. Přidáme proto k příkazu parametr --bare:

[gitserver:/]$ cd /home/git/repositories/projekt.git
[gitserver:/home/git/repositories/projekt.git]$ git --bare init
Initialized empty Git repository in /home/git/repositories/projekt.git/

Repozitář je nyní připravený a můžeme do něj zapsat z lokálního počítače první commit:

[localhost:~]$ mkdir ~/projekt-l.git
[localhost:~]$ cd ~/projekt-l.git
[localhost:~/projekt-l.git]$ git init
[localhost:~/projekt-l.git]$ touch ZADANI
[localhost:~/projekt-l.git]$ git add ZADANI
[localhost:~/projekt-l.git]$ git commit -m "Pridano zadani"
[localhost:~/projekt-l.git]$ git remote add gitserver git@gitserver:repositories/projekt.git
[localhost:~/projekt-l.git]$ git push gitserver master

Stejně tak jej můžeme klonovat:

[localhost:~]$ mkdir ~/projekt-clone.git
[localhost:~]$ cd ~/projekt-clone.git
[localhost:~/projekt-clone.git]$ git clone git@gitserver:repositories/projekt.git

Všichni uživatelé, kteří mají svůj SSH klíč na serveru v souboru /home/git/authorized_keys mohou s repozitářem pracovat, mají k němu plná práva. Přístup k serveru mají také přes SSH, což není vždy žádoucí. Změnou shellu uživatele git na shell /usr/bin/git-shell v /etc/passwd jim tento přístup můžeme odebrat. Při pokusu o přístup k serveru pod uživatelem git bude uživatelům vracena tato hláška:

[localhost:~]$ ssh git@gitserver
fatal: What do you think I am? A shell?
Connection to gitserver closed

My tuto změnu kvůli následnému použití nástroje Gitosis provádět nebudeme. Tím máme první část zadání hotovou. Nyní uživatelům umožníme zobrazovat obsah repozitáře v internetovém prohlížeči.

Gitweb – webové rozhraní GITu

Gitweb je CGI skript představující webové rozhraní pro GIT repozitáře. V tomto článku předpokládám na serveru připravený webový server Apache, který bude Gitweb obsluhovat. Nejdříve vytvoříme nového VirtualHost-a:

[gitserver:/]$ cd /etc/httpd/vhosts.d/
[gitserver:/etc/httpd/vhosts.d]$ touch gitweb.conf

Obsah gitweb.conf bude vypadat takto:

<VirtualHost *:80>
    ServerName gitserver
    DocumentRoot /srv/vhosts/gitweb
    <Directory /var/www/git>
        Options ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch
        AllowOverride All
        order allow,deny
        Allow from all
        AddHandler cgi-script cgi
        DirectoryIndex gitweb.cgi
    </Directory>
</VirtualHost>

Z obsahu je jasně, že Apache bude očekávat Gitweb v adresáři /srv/vhosts/gitweb. Nejdříve nainstalujeme Gitweb z balíčku:

[gitserver:/]$ yum install gitweb

Po instalaci se nachází v adresáři /var/www/git, přesuneme ho proto do adresáře /srv/vhosts/gitweb.

[gitserver:/]$ mkdir /srv/vhosts/gitweb
[gitserver:/]$ cp -r /var/www/git/* /srv/vhosts/gitweb/

Otevřeme skript /srv/vhosts/gitweb/gitweb.cgi a upravíme v něm cestu k našim repozitářům:

our $projectroot = "/home/git/repositories";

Aby mohl Apache přistupovat do domácího adresáře uživatele git, přidáme jej do jeho skupiny. Skupině přiřadíme práva čtení a spouštění:

[gitserver:/]$ usermod -G git apache
[gitserver:/]$ chmod g+rx /home/git

Spustíme webový server Apache:

[gitserver:/]$ /etc/init.d/httpd start

Na lokálním počítači si v souboru /etc/hosts nastavíme překládání adresy gitserver na ip adresu gitserveru (v mém případě je to 192.168.1.4):

192.168.1.4	gitserver

Nyní v internetovém prohlížeči můžeme přejít na adresu http://gitserver kde se nám zobrazí rozhraní Gitwebu:

Protože uživatele nechceme mučit základním vzhledem, nainstalujeme jim vzhled od Stefana Imhoffa (https://github.com/kogakure/gitweb-theme) inspirovaný službou github.com:

[gitserver:/tmp]$ git clone https://github.com/kogakure/gitweb-theme.git
[gitserver:/tmp]$ cp gitweb-theme/gitweb.css /srv/vhosts/gitweb/

Výsledné rozhraní Gitwebu pro uživatele vypadá takto:

Tímto jsme uživatelům zpřístupnili webové rozhraní pro zobrazení repozitářů. Abychom splnili zadání, musíme ještě uživatelům přiřadit práva pro přístup k repozitářům. K tomu použijeme nástroj Gitosis.

Gitosis – nástroj pro správu GIT repozitářů

Nejdříve si naklonujeme repozitář s Gitosis a nainstalujeme ho:

[gitserver:/tmp]$ git clone git://eagain.net/gitosis.git
[gitserver:/tmp]$ cd gitosis
[gitserver:/tmp/gitosis]$ python setupy.py install

Nyní je ho potřeba inicializovat. Gitosis se vždy inicializuje do domácího adresáře uživatele pod kterým je skript gitosis-init spuštěn, proto jej musíme spustit pod uživatelem git. Zároveň se Gitosis při inicializaci sám postará o vložení veřejného SSH klíče do souboru authorized_keys, odstraníme tedy z authorized_keys klíč který jsme do něj dříve přidali:

[gitserver:/home/git]$ echo "" > .ssh/authorized_keys
[gitserver:/home/git]$ gitosis-init < /tmp/id_dsa.pub
[gitserver:/home/git]$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub
Initialized empty Git repository in ./
Reinitialized existing Git repository in ./

V adresáři /home/git/repositories se vytvořil repozitář s názvem gitosis-admin.git. Naklonujeme si ho na lokální počítač:

[localhost:~]$ git clone git@gitserver:gitosis-admin.git

Obsahem repozitáře je soubor gitosis.conf a adresář keydir. V adresáři keydir se uchovávají SSH klíče všech uživatelů, gitosis.conf zatím obsahuje defaultní konfiguraci. Do adresáře keydir nakopírujeme veřejné klíče uživatelů user1, user2 a user3:

[localhost:~/gitosis-admin]$ cp /tmp/user1.pub /tmp/user2.pub /tmp/user3.pub keydir/

A v souboru gitosis.conf upravíme konfiguraci dle zadání:

[gitosis]

[group gitosis-admin]
writable = gitosis-admin
members = filip

[group programatori]
writable = projekt
members = user1 user2

[group programatori_readonly]
readonly = projekt
members = user3

V konfiguraci jsme vytvořili skupinu programatori, která může zapisovat do repozitáře projekt.git. Do skupiny jsme přiřadili uživatele user1 a user2 (název uživatele odpovídá názvu souboru s SSH klíčem v adresáři keydir bez koncovky .pub). Další skupina se nazývá programatori_readonly. Tato skupina má pouze práva ke čtení repozitáře projekt.git. Do skupiny jsme přiřadili uživatele user3. Zbývá změny nahrát zpět na server:

[localhost:~/gitosis-admin]$ git add *
[localhost:~/gitosis-admin]$ git commit -m "Pridana skupina programatoru"
[localhost:~/gitosis-admin]$ git push

Je na čase konfiguraci otestovat:

[user1@localhost:~]$ git clone git@gitserver:projekt.git

Initialized empty Git repository in /home/user1/projekt/.git/
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

[user1@localhost:~]$ cd projekt
[user1@localhost:~/projekt]$ touch POZNAMKY
[user1@localhost:~/projekt]$ git add POZNAMKY
[user1@localhost:~/projekt]$ git commit -m "pridany poznamky"
[user1@localhost:~/projekt]$ git push

Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 244 bytes, done.
Total 2 (delta 0), reused 0 (delta 0)
To git@gitserver:projekt.git
   6f421f2..51f184f  master -> master
[user3@localhost:~]$ git clone git@gitserver:projekt.git

Initialized empty Git repository in /home/user3/projekt/.git/
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (5/5), done.

[user3@localhost:~]$ cd projekt
[user3@localhost:~/projekt]$ echo "@user3" > POZNAMKY
[user3@localhost:~/projekt]$ git commit -a -m "Pridana poznamka od uzivatele user3"
[user3@localhost:~/projekt]$ git push

ERROR:gitosis.serve.main:Repository write access denied
fatal: The remote end hung up unexpectedly

User1 může v pořádku číst i zapisovat do repozitáře zatímco user3 jej může pouze číst. Konfigurace tedy odpovídá zadání.

Další možnosti konfigurace Gitosis

Jak jste si možná všimli, Gitweb zobrazuje kromě repozitáře projekt.git i repozitář gitosis-admin.git. Pokud byste ho radši ve výpisu neměli, stačí upravit konfiguraci. Obsah gitosis.conf upravte takto:

[gitosis]
gitweb = no

[group gitosis-admin]
writable = gitosis-admin
members = filip

[group programatori]
writable = projekt
members = user1 user2

[group programatori_readonly]
readonly = projekt
members = user3

[repo projekt]
gitweb = yes

S touto konfigurací Gitweb bude zobrazovat pouze ty repozitáře, které mají v gitosis.conf explicitně uvedeno jejich zobrazení. Ve skutečnosti to však znamená, že tyto repozitáře bude Gitosis uvádět v souboru /home/git/gitosis/projects.list. Tento seznam tedy musíme předat Gitwebu. Předáme ho změnou řádku v gitweb.conf:

# source of projects list
our $projects_list = "/home/git/gitosis/projects.list";

Po této změně Gitweb zobrazí pouze repozitář projekt.git. Dále je možné v konfiguraci repozitáře nastavit vlastníka a popis repozitáře (zobrazuje Gitweb). To provedete takto:

[repo projekt]
gitweb = yes
owner = Filip Bartoš
description = Testovací projekt

Další možná nastavení najdete v repozitáři Gitosis-u v souboru example.conf.

Kam dál?

Pro další informace o GITu doporučuji navštivit tyto zdroje:

http://progit.org/
http://whygitisbetterthanx.gitfu.cz/
http://gitcasts.com/

Autorem všech těchto webů je Scott Chacon. ProGit byl přeložen do češtiny společností CZ.NIC. V .pdf si ji můžete stáhnout zde: http://knihy.nic.cz/.

2 komentáře u „Sdílené repozitáře verzovacího systému GIT (git, gitweb, gitosis)