-
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.2 Гит изнутра - Гит објекти
Гит објекти
Гит је фајл систем који се адресира садржајем. Одлично. Али шта то значи? Значи да је у срцу програма Гит једноставно складиште парова кључ-вредност. Можете да убаците било какав садржај у Гит репозиторијум и он ће вам вратити јединствени кључ који касније можете употребити да дођете до тог садржаја.
Да бисте ово показали, хајде да видимо водоводну команду hash-object
која узима неке податке, чува их у директоријуму .git/objects
(у бази података објеката) и враћа вам јединствени кључ који од сада показује на тај објекат података.
Најпре иницијализујете нови Гит репозиторијум и да се уверите да у директоријуму objects
нема ничега (како се и очекује).
$ git init test
Initialized empty Git repository in /tmp/test/.git/
$ cd test
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
$ find .git/objects -type f
Програм Гит је иницијализовао директоријум objects
и поддиректоријуме pack
и info
, али нема никаквих обичних фајлова.
Сада, хајде да употребимо git hash-object
, креирамо нови објекат података и ручно га сместимо у нову Гит базу података:
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4
У својом најједноставнијем облику, команда git hash-object
би преузела садржај који јој проследите и само вратила јединствени кључ који би се користио да се он сачува у вашу Гит базу података.
Опција -w
говори команди hash-object
да поред тога што врати кључ, сачува и објекат у базу података.
Коначно, опција --stdin
говори команди git hash-object
да садржај за обраду преузме са стандардног улаза; у супротном команда очекује име фајла у којем се налази садржај као последњи аргумент у командној линији.
Излаз из команде је хеш контролна сума дужине четрдесет карактера. Ово је SHA-1 хеш — контролна сума садржаја који чувате, плус заглавља, о коме ћете научити више мало касније. Сада можете да видите како је програм Гит сачувао податке:
$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
Ако поново погледате свој objects
директоријум, видећете да се у њему сада налази фајл за тај нови садржај.
Ово је начин на који програм Гит иницијално смешта садржај — као један фајл за један део садржаја, чије име је SHA-1 контролна сума садржаја и његовог заглавља.
Поддиректоријум добија име по прва два карактера SHA-1 контролне суме, а име фајла је преосталих 38 карактера.
Када се садржај нађе у вашој бази података објеката, можете га испитати командом cat-file
.
Ова команда је нешто као швајцарски војнички нож за инспекцију Гит објеката.
Када јој проследите опцију -p
, наређујете јој да најпре открије врсту садржаја о ком се ради, па да га прикаже на одговарајући начин:
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content
Сада знате како да у програм Гит додате садржај у Гит и да га поново извучете назад. Ово такође можете да радите и са садржајем у фајловима. На пример, можете да обавите једноставну контролу верзије над фајлом. Најпре креирајте нови фајл и сачувајте његов садржај у базу података:
$ echo 'version 1' > test.txt
$ git hash-object -w test.txt
83baae61804e65cc73a7201a7252750c76066a30
Затим допишите неки нов садржај у фајл, па га поново сачувајте:
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
Ваша база података објеката сада садржи две нове верзије фајла (као и први садржај који сте у њу сачували):
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
У овом тренутку можете обрисати локалну копију тог test.txt
фајла, а затим да употребите програм Гит да из базе података објеката вратите или прву верзију коју сте сачували:
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
$ cat test.txt
version 1
или другу верзију:
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
$ cat test.txt
version 2
Али памћење SHA-1 кључа за сваку верзију фајла није практично; сем тога, у фајл систему не чувате име фајла, већ само његов садржај.
Овај тип објекта се зове блоб.
Програм Гит може да вам каже тип објекта било ког објекта у репозиторијуму, ако му уз команду cat-file -t
задате SHA-1 кључ.
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
blob
Објекти стабла
Следећи тип Гит објеката који ћемо испитати је стабло, које решава проблем чувања имена фајлова, а поред тога вам дозвољава и да заједно ускладиштите групу фајлова. Програм Гит садржај чува на сличан начин као Јуникс фајл систем, али нешто једноставније. Сав садржај се састоји од објеката стабала и блобова, при чему стабла одговарају Јуникс директоријумима, а блобови су мање-више пандан и-чворовима или садржају фајлова. Један објекат стабла садржи једну или више ставки, од којих свака садржи SHA-1 хеш блоба или подстабла, уз информацију о придруженом режиму, врсти и имену фајла. На пример, рецимо да имате пројекат у којем најновије стабло изгледа некако овако:
$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
Синтакса master^{tree}
наводи објекат стабла на које показује последњи комит на master
грани.
Обратите пажњу на то да поддиректоријум lib
није блоб већ показивач на друго стабло:
$ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb
Белешка
|
Зависно од љуске коју користите, можете наићи на проблеме при употреби У CMD на Виндоуз систему, карактер Ако користите ZSH, карактер |
Концептуално, подаци које чува програм Гит изгледају отприлике на следећи начин:
Прилично лако можете направити своје сопствено стабло.
Програм Гит обично креира стабло тако што узима стање стејџа или индекса и на основу њега исписује низ објеката стабла.
Дакле, да бисте креирали стабло, прво треба да поставите индекс тако што стејџујете неке фајлове.
Да бисте креирали индекс са само једном ставком — првом верзијом фајла test.txt
— можете да употребите водоводну команду update-index
.
Ова команду можете искористити да на стејџ вештачки додате старију верзију фајла test.txt
.
Морате да јој проследите опцију -add
јер фајл још увек не постоји на стејџу (у овом тренутку немате ни стејџ) и --cacheinfo
јер се фајл који додајете не налази у вашем директоријуму, већ у бази података.
Затим наведете режим, SHA-1 и име фајла:
$ git update-index --add --cacheinfo 100644 \
83baae61804e65cc73a7201a7252750c76066a30 test.txt
У овом случају наводите режим 100644
, што значи да се ради о обичном фајлу.
Остале опције су 100755
, што значи да се ради о извршном фајлу; и 120000
, што наводи симболички линк.
Режим је преузет од уобичајених Јуникс режима али је много мање флексибилан — за фајлове (блобове) у програму Гит важе само ова три режима (мада се други режими користе за поддиректоријуме и подмодуле).
Сада можете да искористите команду write-tree
и испишете стејџ у објекат стабла.
Није потребно да се наведе опција -w
— позив ове команде аутоматски креира објекат стабла из стања индекса ако такво стабло још увек не постоји:
$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt
Такође можете проверити да је ово објекат стабла употребом исте git cat-file
команде коју сте видели раније.
$ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
tree
Сада ћете креирати ново стабло са другом верзијом фајла test.txt
, као и са новим фајлом:
$ echo 'new file' > new.txt
$ git update-index test.txt
$ git update-index --add new.txt
Сада ваш стејџ има нову верзију фајла test.txt
, као и нов фајл new.txt
.
Испишите то стабло (притом бележећи стање стејџа или индекса у објекат стабла) и погледајте како изгледа:
$ git write-tree
0155eb4229851634a0f03eb265b69f5a2d56f341
$ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
Обратите пажњу на то да ово стабло има по ставку за оба фајла и да је SHA-1 фајла test.txt
онај за „верзију 2” од раније (1f7a7a
).
Забаве ради, додаћете прво стабло као поддиректоријум у овом.
Стабла можете учитати на свој стејџ командом git read-tree
.
У овом случају, учитавате постојеће стабло на стејџ као подстабло користећи опцију --prefix
уз команду read-tree
:
$ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git write-tree
3c4e9cd789d88d8d89c1073707c3585e41b0e614
$ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614
040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
Ако радни директоријум креирате из новог стабла које сте управо исписали, добићете два фајла на највишем нивоу радног директоријума и поддиректоријум под именом bak
који садржи прву верзију фајла test.txt
.
Податке које Гит чува за ове структуре можете да замислите овако:
Комит објекти
Ако сте урадили све претходно наведено, сада имате три стабла који представљају различите снимке пројекта који желите да пратите, али остаје проблем од раније: да бисте вратили ранији снимак, морате да упамтите све три SHA-1 вредности. Поред тога немате ни информацију о томе ко је сачувао снимак, када је то учињено, нити зашто. Ово су основни подаци које се бележе у комит објекту.
Да бисте креирали комит објекат, позовите commit-tree
, наведите SHA-1 једног стабла и ако их уопште има, који комит објекти непосредно претходе овом који креирате.
Почните са првим стаблом које сте записали:
$ echo 'first commit' | git commit-tree d8329f
fdf4fc3344e67ab068f836878b6c4951e3b15f3d
Белешка
|
Добићете другачију хеш вредност јер се подаци о времену креирања и аутору разликују. Уз то, мада се било који комит објекат може прецизно репродуковати помоћу ових података, историјски детаљи конструкције ове књиге значе да одштампани комит хешеви можда не одговарају датим комитовима. У наставку овог поглавља, замените наведене комит хешеве и хешеве ознака са вредностима које ви добијете. |
Сада командом cat-file
можете да погледате свој нови комит објекат:
$ git cat-file -p fdf4fc3
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700
First commit
Формат комит објекта је једноставан: наводи вршно стабло за снимак пројекта у том тренутку; комитове родитеље, ако постоје (комит објекат приказан изнад нема ниједног родитеља); информације о аутору/комитеру (што користи user.name
и user.email
конфигурациона подешавања и временску ознаку); празну линију, па затим комит поруку.
Сада ћете записати још два комит објекта, при чему сваки показује на комит који је дошао непосредно пре њега:
$ echo 'Second commit' | git commit-tree 0155eb -p fdf4fc3
cac0cab538b970a37ea1e769cbbde608743bc96d
$ echo 'Third commit' | git commit-tree 3c4e9c -p cac0cab
1a410efbd13591db07496601ebc7a059dd55cfe9
Сваки од три комит објеката показује на један од три стабла снимака које сте креирали.
Зачудо, сада имате праву Гит историју коју можете да погледате командом git log
, ако је покренете са SHA-1 контролном сумом последњег комита.
$ git log --stat 1a410e
commit 1a410efbd13591db07496601ebc7a059dd55cfe9
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:15:24 2009 -0700
Third commit
bak/test.txt | 1 +
1 file changed, 1 insertion(+)
commit cac0cab538b970a37ea1e769cbbde608743bc96d
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:14:29 2009 -0700
Second commit
new.txt | 1 +
test.txt | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:09:34 2009 -0700
First commit
test.txt | 1 +
1 file changed, 1 insertion(+)
Невероватно.
Управо сте операцијама ниског нивоа изградили Гит историју, не користећи ниједну команду корисничког интерфејса.
У суштини, ово је оно што програм Гит ради када покренете команде git add
и git commit
— чува блобове за фајлове који су се променили, ажурира индекс, исписује стабла и комит објекте који указују на вршна стабла и комитове који им непосредно претходе.
Ова три главна Гит објекта — блоб, стабло и комит — се иницијално чувају као посебни фајлови у директоријуму .git/objects
.
Ево свих објеката из тренутног стања нашег директоријума који користимо за овај пример, уз коментар о томе шта чувају:
$ find .git/objects -type f
.git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2
.git/objects/1a/410efbd13591db07496601ebc7a059dd55cfe9 # commit 3
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a # test.txt v2
.git/objects/3c/4e9cd789d88d8d89c1073707c3585e41b0e614 # tree 3
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt v1
.git/objects/ca/c0cab538b970a37ea1e769cbbde608743bc96d # commit 2
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # 'test content'
.git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # tree 1
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt
.git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1
Ako ispratite sve unutrašnje pokazivače, dobićete graf objekata koji izgleda nekako ovako:
Складиште објеката
Раније смо поменули да постоји заглавље које се чува заједно са сваким објектом који комитујете у Гит базу података објеката. Погледајмо накратко како Гит чува своје објекте. Видећете како да сачувате блоб објекат — у овом случају, стринг „what is up, doc?”. — интерактивно у језику Руби.
Интерактивни Руби режим покрећете командом irb
.
$ irb
>> content = "what is up, doc?"
=> "what is up, doc?"
Програм Гит конструише заглавље које почиње навођењем врсте објекта — у овом случају је то блоб. Затим му додаје размак иза којег следи величина у бајтовима, па на крају null бајт:
>> header = "blob #{content.bytesize}\0"
=> "blob 16\u0000"
Програм Гит надовезује на заглавље оригинални садржај, па онда рачуна SHA-1 контролну суму тог новог садржаја.
SHA-1 вредност стринга у Рубију можете да израчунате укључивањем SHA-1 digest библиотеке командом require
, а онда позивањем Digest::SHA1.hexdigest()
за стринг.
>> store = header + content
=> "blob 16\u0000what is up, doc?"
>> require 'digest/sha1'
=> true
>> sha1 = Digest::SHA1.hexdigest(store)
=> "bd9dbf5aae1a3862dd1526723246b20206e5fc37"
Хајде да ово упоредимо са излазом команде git hash-object
.
Овде користимо echo -n
да спречимо додавање прелома реда у улаз.
$ echo -n "what is up, doc?" | git hash-object --stdin
bd9dbf5aae1a3862dd1526723246b20206e5fc37
Програм Гит компресује нови садржај користећи zlib, што можете да урадите у Рубију користећи библиотеку zlib.
Прво треба да захтевате библиотеку, па да покренете Zlib::Deflate.deflate()
над садржајем:
>> require 'zlib'
=> true
>> zlib_content = Zlib::Deflate.deflate(store)
=> "x\x9CK\xCA\xC9OR04c(\xCFH,Q\xC8,V(-\xD0QH\xC9O\xB6\a\x00_\x1C\a\x9D"
Коначно, записаћете zlib компресовани садржај на диск.
Одредићете путању објекта који желите да запишете (прва два карактера SHA-1 вредности су име поддиректоријума, а последњих 38 је име фајла унутар тог директоријума).
За креирање поддиректоријума, ако већ не постоји, у Рубију можете да искористите функцију FileUtils.mkdir_p()
.
Затим са File.open()
отворите фајл и позивом методе write()
над враћеном ручком фајла испишете претходно zlib-компресован садржај у фајл:
>> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
=> ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37"
>> require 'fileutils'
=> true
>> FileUtils.mkdir_p(File.dirname(path))
=> ".git/objects/bd"
>> File.open(path, 'w') { |f| f.write zlib_content }
=> 32
Хајде да проверимо садржај објекта командом git cat-file
:
---
$ git cat-file -p bd9dbf5aae1a3862dd1526723246b20206e5fc37
what is up, doc?
---
I to je sve — kreirali ste важећи Git blob objekat.
Сви Гит објекти се чувају на исти начин, само са другачијим типовима — уместо стринга blob, заглавље ће почети са commit или tree. Сем тога, мада садржај блоба може да буде скоро све, садржај комитова и стабала су форматирани на прецизно дефинисан начин.