Osnovno o Git-u


Git je raspodijeljeni sustav za upravljanje revizijama izvornog koda. Razvijen od strane Linusa Torvaldsa za razvoj Linuxa (2005.). Osnovna ideja pri njegovu stvaranju je bila da sustav bude brz i bez nepotrebne komunikacije s poslužiteljem. Zato je svaka kopija repozitorija potpuna, tj. sadrži cijelu povijest razvoja - nije potrebna komunikacija s poslužiteljem za operacije. Poslužitelj služi kao središnji repozitorij na koji se promjene postavljaju i od kuda razni korisnici mogu dohvatiti kod. Git je vrlo moćan te stoga i vrlo složen sustav. Zato se u ovim kratkim uputama spominju samo neke jednostavnije operacije.

        Poslužitelj                                         Korisnik
 +------------------------+                          +--------------------+
 |                        |                          |   Lokalna kopija   |
 | Središnji repozitorij  | <<<    git push    <<<   |     ("index")      |
 |      ("index")         +--------------------------+                    |
 |                        | >>> git clone/pull >>>   |   Radna inačica    |
 |                        |                          |  ("working tree")  |
 +------------------------+                          +--------------------+
     (npr. github.com)                                 (lokalno računalo)

                  Slika 1. Pojednostavljena arhitektura sustava

Središnji repozitorij (najčešće javni, "index") nalazi se na udaljenom poslužitelju. Na njemu se nalazi do sada objavljeni kod, zajedno sa svom poviješću promjena. Za prvi dohvat tog repozitorija lokalno koristi se naredba clone. Za kasniji dohvat promjena (kad već postoji lokalni) sa središnjee repozitorija koristi se pull.

Kod svakog korisnika git repozitorija nalazi se kopija središnjeg repozitorija ("index"), u poddirektoriju .git. Taj se repozitorij ne koristi izravno, već isključivo preko naredbe git. Osim kopije, kod korisnika se nalazi i radna inačica koda ("working tree") koja sadrži izvorni kod, tj. sve datoteke koje čine repozitorij, a koje korisnik može mijenjati. Primjerice, ako se repozitorij (korisni sadržaj) sastoji od direktorija src, doc i datoteke README, tada će u direktoriju gdje se repozitorij nalazi lokalno kod korisnika uz navedeno biti i direktorij .git prem idućoj slici.

.git    =>  lokalna kopija ("index"), ne dirati (koristi ga naredba git)
doc     \
src      >  radna inačica ("working tree")
README  /

   Slika 2. Primjer lokalnog direktorija s kopijom repozitorija

Korisnik radi promjene lokalno (u direktorijima doc, src, datoteci README i ostalima koje ovdje dodaje), prihvaća te promjene (naredbom add označava ono što želi prihvatiti, a naredbom commit ih "prihvaća") čime se one zapisuju u direktorij .git te nakon toga te prihvaćene promjene (ono što je "commit"-ano) objavljuje na poslužitelju (naredba push).

Kad je korisnik zadovoljan promjenom koju je napravio on ju najprije dodaje u lokalni repozitorij (u .git) naredbama add i commit, a nakon toga, da bi promjene bile vidljive i ostalim korisnicima, promjene treba sinkronizirati s poslužiteljem naredbom push. Korisnik može napraviti više lokalnih promjena i dodavanja u lokalni repozitorij prije nego li te promjene pohrani i na poslužitelj. Za dodavanje svojih promjena u središnji repozitorij korisnik mora imati odgovarajuće dozvole na poslužitelju.

U nastavku je prikazan kratki primjer rada s repozitorijem navođenjem naredbi te povremeno i dodatnog komentara.

$ git clone https://github.com/ljelenkovic/example.git git-example
Cloning into 'git-example'...
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
Checking connectivity... done.

$ cd git-example
$ ls -al
total 20
drwxrwxr-x 3 leonardo leonardo 4096 Vel 16 18:59 ./
drwxrwxr-x 9 leonardo leonardo 4096 Vel 16 18:59 ../
drwxrwxr-x 8 leonardo leonardo 4096 Vel 16 18:59 .git/
-rw-rw-r-- 1 leonardo leonardo  223 Vel 16 18:59 .gitignore
-rw-rw-r-- 1 leonardo leonardo   32 Vel 16 18:59 README.md
$
$ vi hello.c
Uneseno kroz uređivač teksta:
#include <stdio.h>

int main ()
{
	printf ( "Hello Git user!\n" );

	return 0;
}
Prevođenje, pokretanje, ...
$ gcc hello.c
$ ./a.out
Hello Git user!
Stanje lokalnog repozitorija može se provjeriti naredbom status.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	hello.c

nothing added to commit but untracked files present (use "git add" to track)
Iako u direktoriju postoji i datoteka a.out ona se ne gleda stoga što je u datoteci .gitignore (koja se nalazi u početnom direktoriju) navedeno i *.out, tj. rečeno je da se navedene datoteke ignoriraju - ne čine izvorni kod, već su samo pomoćne datoteke koje nastaju pri prevođenju i koje nije potrebno pohranjivati na poslužitelj.
$ git add hello.c
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   hello.c
Prije prvog stavljanja datoteka u lokalni repozitori, git sustav traži da se korisnik predstavi. To je osobito značajno ako na projektu radi više osoba. "Predstavljanje" korisnika se može napraviti globalno (na razini korisnika za svaki repozitorij) ili za svaki projekt zasebno. Idućim naredbama postavlja se identifikacija korisnika samo za trenutni projekt (koji pripada direktoriju u kojem se nalazimo).
$ git config user.name "Ime Prezime"
$ git config user.email "email@adresa"
Dodavanje označenih promjena u lokalni repozitorij obavlja se naredbom commit, a postavljanje tih promjena ("tih commit-ova") na git poslužitelj obavlja se naredbom push.
$ git commit -m "dodan hello.c"
[master fb0647c] dodan hello.c
 1 file changed, 8 insertions(+)
 create mode 100644 hello.c
$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean
$
$ git push origin master
Username for 'https://github.com': ljelenkovic
Password for 'https://ljelenkovic@github.com':
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 395 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/ljelenkovic/example.git
   110ef3c..fb0647c  master -> master
Umjesto cijele naredbe git push origin master može se navesti i samo git push. Međutim, tada se u ispisu može pojaviti i poruka koja sugerira korisniku da odabere način pohranjivanja "grana" (branch) na udaljeni repozitorij (obzirom da u naredbi nije određeno u koju granu pohranjujemo trenutno aktivnu. Naredbom git config push.default matching kažemo da sa git push pohrani sve lokalne grane na poslužitelj pod istim imenima. Ona druga opcija (simple) će pohraniti samo trenutno aktivnu granu.

Ukoliko ima promjena na središnjem repozitoriju koje nisu ažurirane lokalno (npr. neki drugi korisnik je u međuvremenu postavio svoje promjene na poslužitelj) tada se preko naredbe pull može ažurirati lokalni repozitorij.

$ git pull origin master
From https://github.com/ljelenkovic/example
 * branch            master     -> FETCH_HEAD
Already up-to-date.