-
1. Почетак
- 1.1 О контроли верзије
- 1.2 Кратка историја програма Гит
- 1.3 Шта је Гит?
- 1.4 Командна линија
- 1.5 Инсталирање програма Гит
- 1.6 Подешавања за први пут
- 1.7 Тражење помоћи
- 1.8 Резиме
-
2. Основе програма Гит
- 2.1 Прављење Гит репозиторијума
- 2.2 Снимање промена над репозиторијумом
- 2.3 Преглед историје комитова
- 2.4 Опозив
- 2.5 Рад са удаљеним репозиторијумима
- 2.6 Означавање
- 2.7 Гит алијаси
- 2.8 Резиме
-
3. Гранање у програму Гит
- 3.1 Укратко о гранању
- 3.2 Основе гранања и спајања
- 3.3 Управљање гранама
- 3.4 Процеси рада са гранањем
- 3.5 Удаљене гране
- 3.6 Ребазирање
- 3.7 Резиме
-
4. Гит на серверу
- 4.1 Протоколи
- 4.2 Постављање програма Гит на сервер
- 4.3 Генерисање јавног SSH кључа
- 4.4 Подешавање сервера
- 4.5 Гит демон
- 4.6 Паметан HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Опције за хостовање које нуде трећа лица
- 4.10 Резиме
-
5. Дистрибуирани Гит
-
6. GitHub
-
7. Гит алати
- 7.1 Избор ревизија
- 7.2 Интерактивно стејџовање
- 7.3 Скривање и чишћење
- 7.4 Потписивање вашег рада
- 7.5 Претрага
- 7.6 Поновно исписивање историје
- 7.7 Демистификовани ресет
- 7.8 Напредно спајање
- 7.9 Rerere
- 7.10 Отклањање грешака са програмом Git
- 7.11 Подмодули
- 7.12 Паковање
- 7.13 Замена
- 7.14 Складиште акредитива
- 7.15 Резиме
-
8. Прилагођавање програма Гит
- 8.1 Конфигурисање програма Гит
- 8.2 Гит атрибути
- 8.3 Гит куке
- 8.4 Пример полисе коју спроводи програм Гит
- 8.5 Резиме
-
9. Гит и остали системи
- 9.1 Гит као клијент
- 9.2 Мигрирање на Гит
- 9.3 Резиме
-
10. Гит изнутра
- 10.1 Водовод и порцелан
- 10.2 Гит објекти
- 10.3 Гит референце
- 10.4 Pack фајлови
- 10.5 Рефспек
- 10.6 Протоколи за пренос
- 10.7 Одржавање и опоравак податак
- 10.8 Променљиве окружења
- 10.9 Резиме
-
A1. Додатак А: Програм Гит у другим окружењима
- A1.1 Графички интерфејси
- A1.2 Гит у Visual Studio
- A1.3 Гит у Visual Studio Code
- A1.4 Гит у IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Гит у Sublime Text
- A1.6 Гит унутар Bash
- A1.7 Гит у Zsh
- A1.8 Гит у Powershell
- A1.9 Резиме
-
A2. Додатак Б: Уграђивање програма Гит у ваше апликације
- A2.1 Гит из командне линије
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Додатак В: Гит команде
- A3.1 Подешавање и конфигурација
- A3.2 Набављање и креирање пројеката
- A3.3 Основно снимање
- A3.4 Гранање и спајање
- A3.5 Дељење и ажурирање пројеката
- A3.6 Инспекција и поређење
- A3.7 Отклањање грешака
- A3.8 Крпљење
- A3.9 Имејл
- A3.10 Спољни системи
- A3.11 Администрација
- A3.12 Водоводне команде
10.6 Гит изнутра - Протоколи за пренос
Протоколи за пренос
Програм Гит може да преноси податке између два репозиторијума на два главна начина: „приглуп” протокол и „паметни” протокол. Овај одељак ће укратко представити начин на који функционишу ови главни протоколи.
Приглуп протокол
Ако постављате репозиторијум који ће да се сервира само-за-читање преко HTTP, највероватније ћете употребити приглуп протокол.
Овај протокол се назива „приглуп” јер током процеса преноса на серверској страни није потребан никакав Гит специфични кôд; процес преузимања је низ HTTP GET
захтева, а клијент може да претпостави распоред Гит репозиторијума на серверу.
Белешка
|
У данашње време се приглуп протокол прилично ретко користи. Не може лако да се обезбеди или учини приватним, тако да ће већина Гит хостова (и оних базираних на облаку и оних унутар фирми) одбити да га користи. У општем случају се саветује да се користи паметни протокол који ћемо описати мало касније. |
Хајде да испратимо http-fetch
процес за simplegit библиотеку:
$ git clone http://server/simplegit-progit.git
Прва ствар коју ова команда ради је да повуче info/refs
фајл.
Овај фајл исписује команда update-server-info
и то је разлог због којег то морате да укључите као post-receive
куку да би HTTP транспорт функционисао како треба:
=> GET info/refs
ca82a6dff817ec66f44342007202690a93763949 refs/heads/master
Сада имате листу удаљених референци и SHA-1 контролне суме. Затим, погледате шта је HEAD референца, тако да знате шта да одјавите када завршите:
=> GET HEAD
ref: refs/heads/master
Када завршите процес, морате да одјавите master
грану.
Сада сте спремни да почнете са извршавањем корака процеса.
Пошто је почетна тачка ca82a6
комит објекат који сте видели у info/refs
фајлу, крећете да га преузимате:
=> GET objects/ca/82a6dff817ec66f44342007202690a93763949
(179 bytes of binary data)
Враћа вам се објекат – тај објекат је слободан на серверу, а преузели сте га статичким HTTP GET захтевом. Можете да га распакујете са zlib, одбаците заглавље и погледате садржај комита:
$ git cat-file -p ca82a6dff817ec66f44342007202690a93763949
tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
author Scott Chacon <schacon@gmail.com> 1205815931 -0700
committer Scott Chacon <schacon@gmail.com> 1240030591 -0700
Change version number
Затим, постоји још два објекта које треба да преузмете – cfda3b
, што је стабло садржаја на који управо преузети комит указује; и 085bb3
, што је родитељ комит:
=> GET objects/08/5bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
(179 bytes of data)
Овим добијате свој наредни комит објекат. Дохватите објекат стабла:
=> GET objects/cf/da3bf379e4f8dba8717dee55aab78aef7f4daf
(404 - Not Found)
Уупс – изгледа да објекат стабла није слободан на серверу, па вам се враћа 404 одговор. За ово постоји неколико разлога – објекат би могао да се налази у алтернативном репозиторијуму, или би могао да буде унутар pack фајла у овом репозиторијуму. Програм Гит најпре проверава постоји ли наведена било која алтернатива:
=> GET objects/info/http-alternates
(empty file)
Ако ово буде листа алтернативних URL адреса, програм Гит тамо проверава слободне фајлове и pack фајлове – ово је одличан механизам да пројекти који су рачве један другог деле објекте на диску.
Међутим, пошто у овом случају нису наведене никакве алтернативе, ваш објекат мора да се налази у pack фајлу.
Да бисте видели постојеће pack фајлове на овом серверу, морате да преузмете фајл objects/info/packs
који садржи списак ових фајлова (такође га генерише команда update-server-info
):
=> GET objects/info/packs
P pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
Постоји само један pack фајл на серверу, тако да се ваш објекат очигледно тамо налази, али ипак ћете проверити индекс фајл чисто да будете сигурни. Ово је такође корисно ако на серверу постоји више pack фајлова, тако да видите који pack фајл садржи објекат који вам је потребан:
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.idx
(4k of binary data)
Сада када имате индекс pack фајла, можете видети да ли се у њему налази ваш објекат – пошто индекс наводи SHA-1 суме објеката који се налазе у pack фајлу и помераје до тих објеката. Ваш објекат се тамо налази, па хајде да преузмемо комплетан pack фајл:
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
(13k of binary data)
Дошли сте до вашег објекта стабла, па настављате да се крећете кроз комитове.
И они се налазе унутар pack фајла који сте управо преузели, тако да не морате да шаљете још захтева серверу.
Програм Гит одјављује радну копију master
гране на коју указује HEAD референца коју се преузели на почетку.
Паметни протокол
Приглуп протокол је једноставан али није довољно ефикасан и не подржава упис података са клијента на сервер. Паметни протокол је метод за пренос података који се обично користи, али на удаљеној страни је неопходан процес који је интелигентан у вези програма Гит – он може да чита локалне податке, одреди шта клијент има и шта му је потребно, па да за то генерише прилагођени pack фајл. Постоје два скупа процеса за пренос података: пар за слање података на сервер и пар за преузимање података са сервера.
Слање података на сервер
Када треба да пошаље податке на сервер, програм Гит користи send-pack
и receive-pack
процесе.
Процес send-pack
се извршава на клијенту и повезује се са receive-pack
процесом на удаљеној страни.
SSH
На пример, рецимо да у свом пројекту извршите git push origin master
, а да је origin
дефинисано као URL адреса која користи SSH протокол.
Програм Гит покреће send-pack
процес који успоставља везу са вашим сервером преко SSH.
Он покушава да на удаљеном серверу изврши команду путем SSH позива који изгледа некако овако:
$ ssh -x git@server "git-receive-pack 'simplegit-progit.git'"
00a5ca82a6dff817ec66f4437202690a93763949 refs/heads/master□report-status \
delete-refs side-band-64k quiet ofs-delta \
agent=git/2:2.1.1+github-607-gfba4028 delete-refs
0000
Команда git-receive-pack
тренутно враћа одговор који има по једну линију за сваку референцу коју тренутно има – у овом случају само master
грану у њен SHA-1 хеш.
Прва линија такође има и листу могућности сервера (овде су то report-status
, delete-refs
, и још неке, укључујући стринг идентификатор клијента).
Подаци се преносе у комадима. Свака линија почиње са хекс вредности дужине 4 карактера која наводи дужину остатка линије. Ваша прва линија почиње са 005b, што је хексадецимална представа броја 91, па значи да на тој линији преостаје још 91 бајт. Наредна линија почиње са 003e, што је 62, тако да читате преосталих 62 бајтова. Наредна линија је 0000, што значи да је сервер завршио са листањем референци.
Сада када зна стање сервера, ваш send-pack
процес одређује које комитове поседује, а још нису на серверу.
За сваку референцу коју ће ово гурање да ажурира, процес send-pack
преноси процесу receive-pack
ту информацију.
На пример, ако ажурирате master
грану и додајете experiment
грану, send-pack
одговор може изгледати отприлике овако:
0076ca82a6dff817ec66f44342007202690a93763949 15027957951b64cf874c3557a0f3547bd83b3ff6 \
refs/heads/master report-status
006c0000000000000000000000000000000000000000 cdfdb42577e2506715f8cfeacdbabc092bf63e8d \
refs/heads/experiment
0000
Програм Гит шаље по линију за сваку референцу коју ажурирате у којој се налази дужина линије, стара SHA-1 сума, нова SHA-1 сума и референца која се ажурира. У првој линије се налазе и могућности клијента. Ако се SHA-1 вредност састоји само од нула, то значи да раније није било ничега – јер додајете експеримент референцу. Ако бришете референцу, видели бисте супротно: све нуле са десне стране.
Затим, клијент шаље pack фајл свих објеката које сервер још увек нема. Коначно, сервер одговара тако што означава успех (или неуспех):
000eunpack ok
HTTP(S)
Овај процес је углавном исти као и преко HTTP, мада је руковање донекле другачије. Успостављање везе се започиње следећим захтевом:
=> GET http://server/simplegit-progit.git/info/refs?service=git-receive-pack
001f# service=git-receive-pack
00ab6c5f0e45abd7832bf23074a333f739977c9e8188 refs/heads/master□report-status \
delete-refs side-band-64k quiet ofs-delta \
agent=git/2:2.1.1~vmg-bitmaps-bugaloo-608-g116744e
0000
То је крај прве клијент-сервер размене.
Клијент затим шаље наредни захтев, овога пута POST
, са подацима које достави git-upload-pack
.
=> POST http://server/simplegit-progit.git/git-receive-pack
У товару POST
захтева се налази излаз из send-pack
и pack фајл.
Сервер затим својим HTTP одговором означава успех или неуспех.
Имајте на уму да HTTP протокол ове податке може додатно да обмота у пренос по комадима.
Преузимање података са сервера
Када преузимате податке, укључени су fetch-pack
и upload-pack
процеси.
Клијент покреће fetch-pack
процес који се повезује са upload-pack
процесом на удаљеној страни и преговара о томе који подаци ће се пренети.
SSH
Ако преузимање обављате преко SSH, fetch-pack
извршава нешто отприлике овако:
$ ssh -x git@server "git-upload-pack 'simplegit-progit.git'"
Након што се fetch-pack
повеже, upload-pack
шаље назад нешто отприлике овако:
00dfca82a6dff817ec66f44342007202690a93763949 HEAD□multi_ack thin-pack \
side-band side-band-64k ofs-delta shallow no-progress include-tag \
multi_ack_detailed symref=HEAD:refs/heads/master \
agent=git/2:2.1.1+github-607-gfba4028
003fe2409a098dc3e53539a9028a94b6224db9d6a6b6 refs/heads/master
0000
Ово је врло слично одговору који шаље receive-pack
, али су другачије могућности.
Уз то, шаље назад и оно на шта показује HEAD (symref=HEAD:refs/heads/master
) тако да клијент зна шта да одјави ако је у питању клонирање.
У овом тренутку fetch-pack
процес тражи објекте које има и враћа одговор са објектима који су му потребни, тако што пошаље „want и онда SHA-1 хеш онога што ми је потребно.
Све објекте које већ им шаље са „have” и онда SHA-1.
На крају ове листе исписује „done” чиме сигнализира процесу upload-pack
да започне слање pack фајла са подацима који су потребни:
003cwant ca82a6dff817ec66f44342007202690a93763949 ofs-delta
0032have 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
0009done
0000
HTTP(S)
Руковање за операцију преузимања подразумева два HTTP захтева.
Први је GET
исте крајње тачке која се користи и у приглупом протоколу:
=> GET $GIT_URL/info/refs?service=git-upload-pack
001e# service=git-upload-pack
00e7ca82a6dff817ec66f44342007202690a93763949 HEAD□multi_ack thin-pack \
side-band side-band-64k ofs-delta shallow no-progress include-tag \
multi_ack_detailed no-done symref=HEAD:refs/heads/master \
agent=git/2:2.1.1+github-607-gfba4028
003fca82a6dff817ec66f44342007202690a93763949 refs/heads/master
0000
Ово веома личи на позив git-upload-pack
преко SSH везе, али се друга размена обавља као одвојени захтев:
=> POST $GIT_URL/git-upload-pack HTTP/1.0
0032want 0a53e9ddeaddad63ad106860237bbf53411d11a7
0032have 441b40d833fdfa93eb2908e52742248faf0ee993
0000
Још једном, ово је исти формат као и раније. Одговор на овај захтев означава успех или неуспех и садржи pack фајл.
Резиме протокола
Овај одељак садржи доста упрошћени преглед протокола за пренос.
Протокол има још доста других могућности, као што су multi_ack
или side-band
могућности, али је њихово разматрање ван оквира ове књиге.
Покушали смо да вам представимо општу размену између клијента и сервера; ако желите више знања о овоме, вероватно би требало да погледате у изворни кôд програма Гит.