Git
Chapters ▾ 2nd Edition

10.3 Гит изнутра - Гит референце

Гит референце

Ако вас интересује да погледате историју која је доступна из комита, рецимо 1a410e, могли бисте да извршите нешто као што је git log 1a410e што ће вам приказати ту историју, али ипак бисте морали да запамтите да је 1a410e комит који желите користити као почетну тачку за ту историју. Уместо тога би било лакше да имате фајл у који би могли да сачувате ту SHA-1 вредност под једноставним именом тако уместо сирове SHA-1 вредности можете употребити то просто име.

У програму Гит, ти објекти се називају „референце” или „рефови”; у директоријуму .git/refs можете да пронађете фајлове које садрже те SHA-1 вредности. У тренутном пројекту, овај директоријум нема фајлове, али садржи једноставну структуру:

$ find .git/refs
.git/refs
.git/refs/heads
.git/refs/tags
$ find .git/refs -type f

Ако желите да креирате нову референцу која ће вам помоћи да запамтите где се налази последњи комит, технички можете да урадите нешто једноставно као што је ово:

$ echo "1a410efbd13591db07496601ebc7a059dd55cfe9" > .git/refs/heads/master

Сада у Гит командама уместо SHA-1 вредности можете да употребите референцу коју сте управо:

$ git log --pretty=oneline master
1a410efbd13591db07496601ebc7a059dd55cfe9 Third commit
cac0cab538b970a37ea1e769cbbde608743bc96d Second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit

Не саветује се да директно мењате фајлове референци; уместо тога програм Гит нуди сигурнију команду git update-ref која, у случају да желите ажурирати референцу, ради управо то:

$ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9

Ово је у суштини оно што у програму Гит представља грана: једноставан показивач на главу неке линије рада. Да бисте креирали грану на другом комиту, можете да урадите ово:

$ git update-ref refs/heads/test cac0ca

Ваша грана ће садржати само рад почев од тог комита па наниже:

$ git log --pretty=oneline test
cac0cab538b970a37ea1e769cbbde608743bc96d Second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit

Сада ваша база података програма Гит концептуално изгледа некако овако:

Објекти из Гит директоријума са референцама на главе грана
Слика 150. Објекти из Гит директоријума са референцама на главе грана

Када извршите команду као што је git branch <име-гране>, програм Гит у суштини покреће ту update-ref команду како би додао SHA-1 вредност последњег комита гране на којој сте тренутно у коју год нову референцу желите да креирате.

Референца HEAD

Сада се поставља питање: када извршите git branch <име-гране>, како програм Гит зна SHA-1 последњег комита? Одговор је у фајлу HEAD.

Обично је фајл HEAD симболичка референца на грану на којој се тренутно налазите. Под симболичком референцом мислимо на референцу која, за разлику од обичне, садржи показивач на другу референцу.

Међутим, у неким ретким случајевима HEAD фајл може да садржи SHA-1 вредност гит објекта. Ово се дешава када одјавите ознаку, комит, или удаљену грану што оставља ваш репозиторијум у стању „одвојене HEAD” (одвојене главе).

Ако погледате у фајл, обично ћете видети нешто слично овоме:

$ cat .git/HEAD
ref: refs/heads/master

Ако извршите git checkout test, програм Гит ажурира фајл тако изгледала овако:

$ cat .git/HEAD
ref: refs/heads/test

Када извршите git commit, она креира се нови комит објекат, постављајући за родитеља тог комит објекта било коју SHA-1 вредност на коју показује референца у HEAD.

Можете такође и ручно да измените овај фајл; али опет, постоји сигурнија команда да се то уради: symbolic-ref. Вредност ваше HEAD можете да прочитате командом:

$ git symbolic-ref HEAD
refs/heads/master

Истом командом можете и да поставите вредност HEAD:

$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
ref: refs/heads/test

Симболичку референцу не можете да поставите ван refs стила:

$ git symbolic-ref HEAD test
fatal: Refusing to point HEAD outside of refs/

Ознаке

Управо смо завршили дискусију о три главна типа Гит објеката (блобови, стабла и комитови), али постоји и четврти. Објекат ознака (таг) доста подсећа на комит објекат — садржи податке о особи која је додала ознаку, датум, поруку и показивач. Главна разлика је у томе што објекат ознаке у општем случају показује на комит, а не на стабло. Подсећа на референцу гране, али се никад не помера — увек показује на исти комит, с тим што му даје име које је лакше за памћење.

Као што смо видели у поглављу Основе програма Гит, постоје две врсте ознака: прибележене и лаке. Лаке ознаке можете да креирате на следећи начин:

$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d

И то је све што се тиче лаке ознаке — обична референца која се никад не помера. Прибележена ознака је, међутим, доста сложенија. Ако креирате прибележену ознаку, програм Гит креира објекат ознаке и затим пише референцу која показује на рај објекат, а не директно на комит. Ово можете да видите тако што ћете креирати прибележену ознаку (употребом заставице -a):

$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'Test tag'

Ево SHA-1 вредности објекта који је креиран:

$ cat .git/refs/tags/v1.1
9585191f37f7b0fb9444f35a9bf50de191beadc2

Сада извршите команду git cat-file -p над тој SHA-1 вредности:

$ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
object 1a410efbd13591db07496601ebc7a059dd55cfe9
type commit
tag v1.1
tagger Scott Chacon <schacon@gmail.com> Sat May 23 16:48:58 2009 -0700

Test tag

Приметите да object ставка показује на SHA-1 вредност коју сте означили. Такође обратите пажњу и на то да није обавезно да показује на комит; можете означити било који Гит објекат. У изворном коду програма Гит на пример, одржавалац је додао свој GPG јавни кључ као блоб објекат и онда га означио. Јавни кључ можете погледати ако у свом клону Гит репозиторијума извршите ово:

$ git cat-file blob junio-gpg-pub

И репозиторијум Линуксовог језгра има објекте ознака који не показују на комитове — прва направљена ознака показује на иницијално стабло увезеног изворног кода.

Удаљене референце

Трећа врста референци коју ћете виђати су удаљене референце. Ако додате удаљену репозиторијум и гурнете на њега, програм Гит ће у директоријуму refs/remotes чувати вредност коју сте последњу гурнули на тај удаљени репозиторијум за сваку грану. На пример, можете додати удаљени репозиторијум под именом origin и гурнути своју master грану на њега:

$ git remote add origin git@github.com:schacon/simplegit-progit.git
$ git push origin master
Counting objects: 11, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 716 bytes, done.
Total 7 (delta 2), reused 4 (delta 1)
To git@github.com:schacon/simplegit-progit.git
  a11bef0..ca82a6d  master -> master

Након тога можете видети шта је била грана master на удаљеном репозиторијуму origin последњи пут када сте комуницирали са сервером тако што ћете проверити фајл refs/remotes/origin/master:

$ cat .git/refs/remotes/origin/master
ca82a6dff817ec66f44342007202690a93763949

Удаљене референце се разликују од грана (refs/heads референци) углавном по томе што се сматра да могу само да се читају. Можете да урадите get checkout над неком, али програм Гит неће симболички поставити HEAD на неку, тако да је никад нећете ажурирати командом git commit. Програм Гит њима управља као са маркерима последње познатог стања тих грана на тим серверима.