Git
Chapters ▾ 2nd Edition

3.5 Гранање у програму Гит - Удаљене гране

Удаљене гране

Удаљене гране су референце (показивачи) у вашим удаљеним репозиторијумима, укључујући гране, ознаке и тако даље. Комплетну листу удаљених референци можете експлицитно добити командом git ls-remote <име_удаљеног>, или git remote show <име_удаљеног> за удаљене гране заједно са још више информација. Ипак, много чешћи начин је да се искористи предност удаљених праћених грана (remote-tracking branches).

Удаљене праћене гране су референце на стање удаљених грана. Оне су локалне референце које не можете да померите; програм Гит их аутоматски помера када радите било какав вид комуникације преко мреже, тако да обезбеди да прецизно представљају стање удаљеног репозиторијума. Можете да их посматрате као маркере који треба да вас подсете где су се гране у вашим удаљеним репозиторијумима налазиле када сте се последњи пут повезали са њима.

Имена удаљених праћених грана имају облик <име_удаљеног>/<грана>. На пример, ако желите да погледате како је master грана на вашем origin удаљеном репозиторијуму изгледала последњи пут када сте комуницирали са њим, проверили бисте origin/master грану. Ако сте радили на тикету са партнерима који су гурали измене у iss53 грану, ви вероватно имате своју локалну iss53 грану; а на грану која се налази на серверу би показивала удаљена праћена грана origin/iss53.

Ово је може бити помало збуњујуће, па хајде да погледамо пример. Рецимо да на својој мрежи имате Гит сервер на адреси git.ourcompany.com. Ако са њега клонирате, команда clone програма Гит ће то аутоматски назвати origin, повући ће све податке са њега, направиће показивач на место где се налази master грана и локално ће је назвати origin/master. Програм Гит вам такође даје властиту локалну master грану која почиње на истом месту као и master грана на origin репозиторијуму, тако да имате одакле да кренете са радом.

Белешка
origin није ништа посебно

Као што грана са именом „master” у програму Гит нема никакво посебно значење, тако нема ни „origin”. Док је „master” подразумевано име за почетну грану која се добија након команде git init, па је то и једини разлог због кога се тако распрострањено користи, „origin” је подразумевано име за удаљени репозиторијум када извршите git clone. Ако уместо тога извршите git clone -o booyah, онда ће booyah/master бити подразумевана удаљена грана.

Сервер и локални репозиторијуми после клонирања
Слика 30. Сервер и локални репозиторијуми после клонирања

Ако одрадите нешто на локалној master грани, па у међувремену неко други гурне нешто на git.ourcompany.com и ажурира master грану на серверу, онда се ваше историје крећу унапред другачијим током. Такође, све док не ступите у контакт са сервером, origin/master показивач се не помера.

Локални и удаљени рад могу да се разиђу
Слика 31. Локални и удаљени рад могу да се разиђу

Да бисте синхронизовали ваш рад са датим удаљеним репозиторијумом, треба да извршите команду git fetch <име_удаљеног>. Ова команда ће да потражи сервер који је подешен као origin (у овом случају је то git.ourcompany.com), преузме са њега све податке које још увек немате, и ажурира вашу локалну базу података, померајући origin/master показивач на нову, актуелну позицију.

`git fetch` ажурира важе удаљене праћене гране
Слика 32. git fetch ажурира важе удаљене праћене гране

Да бисмо показали ситуацију када имате неколико удаљених сервера и објаснили како изгледају удаљене гране за те удаљене пројекте, хајде да претпоставимо да имате још један интерни Гит сервер који за развој користи само један од ваших спринт тимова. Овај сервер се налази на адреси git.team1.ourcompany.com. Можете да га додате као нову удаљену референцу у пројекат на ком тренутно радите тако што ћете извршити команду git remote add као што смо већ објаснили у Основе програма Гит. Ову удаљену грану назовите teamone, што ће представљати кратко име за тај цео URL.

Додавање још једног удаљеног сервера
Слика 33. Додавање још једног удаљеног сервера

Сада можете да извршите git fetch teamone и преузмете све што се налази на удаљеном серверу teamone, а ви још увек немате. Пошто тај сервер има подскуп података који се тренутно налазе на вашем origin серверу, програм Гит не уопште не преузима податке већ поставља удаљену праћену грану под именом teamone/master која показује на комит који teamone има као своју master грану.

Удаљена праћена грана за `teamone/master`
Слика 34. Удаљена праћена грана за teamone/master

Гурање

Када грану желите да поделите с остатком света, морате да је гурнете ка удаљеном серверу на коме имате право уписа. Ваше локалне гране се неће аутоматски синхронизовати са удаљеним серверима на које уписујете - морате експлицитно да пошаљете („гурнете”) гране које желите да поделите. На тај начин, можете да користите приватне гране за оно што не желите да поделите са осталима, и да гурате само у тематске гране у којима желите да сарађујете.

Ако имате грану која се зове serverfix на којој желите да радите са другима, можете да је гурнете навише на исти начин на који сте гурнули и и своју прву грану. Извршите git push <име_удаљеног> <грана>:

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

Ово је донекле пречица. Програм Гит аутоматски развија име гране serverfix у refs/heads/serverfix:refs/heads/serverfix, што значи „Узми моју локалну serverfix грану и гурни је тако да се ажурира serverfix грана на удаљеном серверу.” Део refs/heads/ ћемо детаљније погледати у Гит изнутра, али у општем случају можете да га изоставите. Можете да урадите и git push origin serverfix:serverfix, што ради исту ствар — каже „Узми моју serverfix грану и уреди да постане serverfix грана удаљеног сервера.”. Овај формат можете употребити да гурнете локалну грану у удаљену грану која има другачије име. Ако не желите да се на удаљеном серверу зове serverfix, можете да извршите git push origin serverfix:awesomebranch чиме локалну serverfix грану гурате у awesomebranch грану на удаљеном пројекту.

Белешка
Немојте да куцате своју лозинку сваки пут

Ако за гурање користите HTTPS URL, Гит сервер ће вас ради аутентификације питати за корисничко име и лозинку. Подразумевано ће вас у терминалу питати за ову информацију тако да сервер може одредити да ли вам је дозвољено да обавите операцију push.

Ако не желите да куцате ове податке сваки пут када вршите гурање, можете да подесите „кеш акредитива”. Најједноставнији начин је да их једноставно задржите у меморији на неколико минута, то лако можете подесити извршавањем git config --global credential.helper cache.

За више информација о разним опцијама за кеширање акредитива које су вам доступне, погледајте Складиште акредитива.

Следећи пут када неко од ваших сарадника преузме податке са сервера, добиће референцу на место где се налази серверова верзија serverfix гране као удаљену грану origin/serverfix:

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

Важно је приметити да када извршите преузимање података, тиме се довлаче и нове удаљене праћене гране, а ви немате аутоматски њихове локалне копије над којима можете да радите. Другим речима, у овом случају ви немате нову serverfix грану - имате само origin/serverfix показивач који не можете да мењате.

Да бисте спојили овај рад у грану на којој тренутно радите, можете да извршите git merge origin/serverfix. Ако желите своју личну serverfix грану на којој ћете да радите, можете да је базирате према удаљеној праћеној грани:

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

Ово вам прави локалну грану на којој можете да радите, а која почиње од места где се налази origin/serverfix.

Гране за праћење

Одјављивање локалне гране од удаљене праћене гране аутоматски креира нешто што се зове „грана за праћење” (а грана коју она прати се назива „узводна грана”). Гране за праћење су локалне гране које имају директну везу са удаљеном граном. Ако сте на грани за праћење и укуцате git pull, програм Гит аутоматски зна са ког сервера треба да преузме податке и у коју грану треба да их споји.

Када клонирате репозиторијум, у општем случају се аутоматски креира master грана која прати origin/master. Међутим, ако желите можете да поставите и друге гране за праћење — оне које прате гране на другим удаљеним серверима, или које не прате master грану. Прост случај је пример који сте управо видели, извршавање git checkout -b <грана> <име_удаљеног>/<грана>. Ова операција је толико честа да за њу програм Гит обезбеђује скраћеницу --track:

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

Уствари, ово се толико често користи да постоји чак и скраћеница ове скраћенице. Ако име гране коју покушавате да одјавите (а) не постоји и (б) потпуно се подудара са именом на само једном удаљеном серверу, програм Git ће за вас креирати грану за праћење:

$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

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

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

Сада ће ваша локална грана sf аутоматски повлачити са origin/serverfix.

Ако већ имате локалну грану и желите да је подесите на удаљену грану коју сте управо повукли, или желите да промените узводну грану коју пратите, можете да уз команду git branch употребите опцију -u или --set-upstream-to чиме је експлицитно задајете у било ком тренутку.

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Белешка
upstream пречица

Када имате подешену грану за праћење, њену узводну грану можете да референцирате пречицом @{upstream} или @{u}. Дакле, ако сте на master грани која прати origin/master, можете уместо git merge origin/master да задате нешто као git merge @{u} ако желите.

Да бисте видели све подешене гране за праћење, употребите опцију -vv уз команду git branch. Ово ће излистати ваше локалне гране са више информација, укључујући и то шта свака од грана прати, као и да ли је локална грана испред, иза или оба.

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] Add forgotten brackets
  master    1ae2a45 [origin/master] Deploy index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it
  testing   5ea463a Try something new

Дакле, овде можемо да видимо да наша iss53 грана прати origin/iss53 и да се налази „испред” за два, што значи да локално имамо два комита која нису гурнута на сервер. Можемо да видимо и то да наша master грана прати origin/master и да је иста као и актуелна верзија на серверу. Даље, видимо да наша serverfix грана прати serverfix-fix-good грану на teamone серверу и да је испред за три и иза за један, што значи да постоји један комит на серверу који још увек нисмо спојили, али и да постоје три локална комита која још увек нисмо гурнули. Коначно, видимо да наша testing грана не прати ниједну удаљену грану.

Важно је запазити да су ови бројеви релативни у односу на тренутак када сте сте последњи пут преузели податке са сервера. Ова команда не ступа у везу са сервером, она вам говори само о ономе што је локално кеширала са тих сервера. Ако желите потпуно прецизне ahead и behind бројеве, мораћете најпре да преузмете податке са свих удаљених сервера пре него што покренете ову команду. То можете урадити на следећи начин:

$ git fetch --all; git branch -vv

Повлачење

Мада ће команда git fetch да преузме све промене на серверу које још увек немате, она уопште неће изменити ваш радни директоријум. Само ће преузети податке и оставиће вама да их спојите. Међутим, постоји команда која се зове git pull која је суштински у већини случајева git fetch за којом непосредно следи git merge. Ако имате грану за праћење подешену на начин који је показан у претходном одељку, било да сте је експлицитно подесили, или сте је добили као резултат команде clone или checkout, git pull ће погледати који сервер и грану ваша грана тренутно прати, преузеће податке са тог сервера и онда ће пробати да их споји у ту грану за праћење.

У општем случају је боље да просто користите fetch и merge команде експлицитно, јер команда git pull често зна да уноси забуну.

Брисање удаљених грана

Претпоставимо да сте завршили са удаљеном граном — рецимо да сте ви и ваши сарадници завршили рад на некој могућности и спојили сте је са master граном вашег удаљеног сервера (или с којом год граном спајате стабилан кôд). Удаљену грану можете да обришете користећи --delete опцију уз команду git push. Ако желите да са сервера обришете вашу serverfix грану, извршите следеће:

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

У суштини, ово само уклања показивач са сервера. Гит сервер ће у општем случају задржати податке тамо неко време док се не покрене garbage collector, тако да ако је грана обрисана случајно, често ће обнова података бити једноставна.