-
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 Водоводне команде
A2.2 Додатак Б: Уграђивање програма Гит у ваше апликације - Libgit2
Libgit2
Још једна доступна опција је да употребите Libgit2. Libgit2 је Гит имплементација која нема зависности, са тежиштем на лепом API која је предвиђена за употребу у другим програмима. Можете да је пронађете на адреси http://libgit2.github.com.
Најпре, хајде да погледамо како изгледа C API. Ево вртоглаве турнеје:
// Open a repository
git_repository *repo;
int error = git_repository_open(&repo, "/path/to/repository");
// Dereference HEAD to a commit
git_object *head_commit;
error = git_revparse_single(&head_commit, repo, "HEAD^{commit}");
git_commit *commit = (git_commit*)head_commit;
// Print some of the commit's properties
printf("%s", git_commit_message(commit));
const git_signature *author = git_commit_author(commit);
printf("%s <%s>\n", author->name, author->email);
const git_oid *tree_id = git_commit_tree_id(commit);
// Cleanup
git_commit_free(commit);
git_repository_free(repo);
Првих неколико линија отвара Гит репозиторијум.
Тип git_repository
представља ручку репозиторијума са кешом у меморији.
Ово је најједноставнија метода, када тачно знате путању до радног директоријума репозиторијума, или до .git
директоријума.
Постоји и git_repository_open_ext
који има опције претраге, git_clone
и пријатељи за креирање локалног клона удаљеног репозиторијума и git_repository_init
за креирање потпуно новог репозиторијума.
Друго парче кода користи rev-parse синтаксу (за више информација о овоме, погледајте Референце грана) да дође до комита на који показује HEAD.
Повратни тип је git_object
показивач, који представља нешто што постоји у Гит бази података објеката за репозиторијум.
git_object
је уствари „родитељски” тип за неколико различитих врста објеката; распоред меморије за сваку врсту „дете” типова је исти као за git_object
, тако да безбедно можете да кастујете у одговарајући.
У овом случају, git_object_type(commit)
би вратило GIT_OBJ_COMMIT
, тако да је безбедно да се кастује у git_commit
показивач.
Следеће парче показује како да се приступи особинама комита.
Последња линија овде користи тип git_oid
; ово је Libgit2 репрезентација SHA-1 хеша.
Из овог примера, почело је да се појављује неколико шаблона:
-
Ако декларишете показивач и проследите референцу на њега у Libgit2 позив, тај позив ће вероватно да врати целобројни кôд грешке. Вредност
0
означава успех; све мање од тога је грешка. -
Ако Libgit2 за вас попуни показивач, ваш је задатак да га ослободите.
-
Ако Libgit2 из позива врати
const
показивач, не морате да га ослободите, али ће престати да важи када се ослободи објекат којем припада. -
Писање C кода је помало болно.
Последње значи да је мало вероватно да ћете писати на језику C када користите Libgit2. На срећу, постоји већи број везивања за одређене језике која знатно олакшавају рад са Гит репозиторијумима из вашег одређеног језика и окружења. Хајде да погледамо претходни пример написан Руби везивањима за Libgit2, која се зову Rugged, и можете да их пронађете на адреси https://github.com/libgit2/rugged.
repo = Rugged::Repository.new('path/to/repository')
commit = repo.head.target
puts commit.message
puts "#{commit.author[:name]} <#{commit.author[:email]}>"
tree = commit.tree
Као што видите, кôд је много мање запетљан.
Прво, Rugged користи изузетке; може да баци ствари као што су ConfigError
или ObjectError
којима сигнализира стања грешке.
Друго, нема експлицитног ослобађања ресурса, јер језик Руби скупља ђубре.
Хајде да погледамо мало компликованији пример: креирање комита од самог почетка:
blob_id = repo.write("Blob contents", :blob) # (1)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(:path => 'newfile.txt', :oid => blob_id) # (2)
sig = {
:email => "bob@example.com",
:name => "Bob User",
:time => Time.now,
}
commit_id = Rugged::Commit.create(repo,
:tree => index.write_tree(repo), # (3)
:author => sig,
:committer => sig, # (4)
:message => "Add newfile.txt", # (5)
:parents => repo.empty? ? [] : [ repo.head.target ].compact, # (6)
:update_ref => 'HEAD', # (7)
)
commit = repo.lookup(commit_id) # (8)
-
Креира нови блоб у којем се налази садржај новог фајла.
-
Попуњава индекс са стаблом head комита, па додаје нови фајл на путању
newfile.txt
. -
Ово креира ново стабло у ODB (бази података објеката), па га користи за нови комит.
-
Користимо исти потпис и за поље аутора и за поље комитера.
-
Комит порука.
-
Када се креира комит, морате да наведете родитеље новог комита. Ово користи врх HEAD референце као једног родитеља.
-
Rugged (и Libgit2) могу необавезно да ажурирају референцу када праве комит.
-
Враћена вредност је SHA-1 хеш новог комит објекта коју онда можете употребити да добијете
Commit
објекат.
Руби кôд је фин и чист, али пошто Libgit2 диже највећи део тежине, овај кôд ће се такође и извршавати прилично брзо. Ако нисте рубиста, дотичемо се и осталих везивања у Остала везивања.
Напредна функционалност
Libgit2 поседује неколико могућности вам опсега Гит језгра. Један од примера је проширивост: Libgit2 вам дозвољава да доставите прилагођене „позадинске механизме” за неколико врста операција, тако да ствари можете складиштити на начин који се разликује од онога који користи програм Гит. Libgit2 између осталог дозвољава прилагођене позадинске механизме за конфигурацију, складиштење референци и базу објеката.
Хајде да видимо како ово функционише. Кôд који следи је позајмљен из скупа примера позадинских механизама које је представио Libgit2 тим (и могу да се пронађу на адреси https://github.com/libgit2/libgit2-backends). Ево како се поставља прилагођени позадински механизам за базу података објеката:
git_odb *odb;
int error = git_odb_new(&odb); // (1)
git_odb_backend *my_backend;
error = git_odb_backend_mine(&my_backend, /*…*/); // (2)
error = git_odb_add_backend(odb, my_backend, 1); // (3)
git_repository *repo;
error = git_repository_open(&repo, "some-path");
error = git_repository_set_odb(odb); // (4)
Приметите да се грешке хватају, али се не обрађују. Надамо се да је ваш кôд бољи од нашег.
-
Иницијализује „чеони део” празне базе података објеката (ODB), која ће служити као контејнер за позадинске механизме који уствари одрађују прави посао.
-
Иницијализује прилагођени ODB позадински механизам.
-
Додаје позадински механизам у чеони део.
-
Отвара репозиторијум и подешава га да користи нашу ODB за претрагу објеката.
Али шта је та git_odb_backend_mine
ствар?
Па, то је конструктор ваше сопствене ODB имплементације и ту можете да урадите штагод желите, док год исправно попуните git_odb_backend
структуру.
Ево како то могло да изгледа:
typedef struct {
git_odb_backend parent;
// Some other stuff
void *custom_context;
} my_backend_struct;
int git_odb_backend_mine(git_odb_backend **backend_out, /*…*/)
{
my_backend_struct *backend;
backend = calloc(1, sizeof (my_backend_struct));
backend->custom_context = …;
backend->parent.read = &my_backend__read;
backend->parent.read_prefix = &my_backend__read_prefix;
backend->parent.read_header = &my_backend__read_header;
// …
*backend_out = (git_odb_backend *) backend;
return GIT_SUCCESS;
}
Најсуптилније ограничење овде је да први члан my_backend_struct
мора бити git_odb_backend
структура; то обезбеђује да распоред меморије буде онакав какав очекује Libgit2 кôд.
Остатак је произвољан; ова структура можете бити велика или мала колико год је то потребно.
Функција иницијализације алоцира нешто меморије за структуру, поставља прилагођени контекст, па затим попуњава чланове parent
структуре коју подржава.
Погледајте фајл include/git2/sys/odb_backend.h
у Libgit2 изворном коду да видите комплетан скуп потписа позива; ваш дати случај коришћења ће вам помоћи да одредите које од њих ћете пожелети да подржите.
Остала везивања
Libgit2 има везивања за много језика.
Ево малог примера који користи неколико комплетних пакета везивања у време писања овог текста; постоје библиотеке за многе друге језике, укључујући C++, Go, Node.js, Erlang и JVM, сви у различитим фазама зрелости.
Званична колекција везивања може да се пронађе прегледом репозиторијума на адреси https://github.com/libgit2.
Кôд који ћемо ми написати ће да враћа комит поруку из комита на који коначно указује HEAD (нешто као git log -1
).
LibGit2Sharp
Ако пишете .NET или Mono апликацију, LibGit2Sharp (https://github.com/libgit2/libgit2sharp) је оно што тражите. Везивања су написана ма C# и посвећено је доста пажње да се сирови Libgit2 позиви умотају у CLR API који изгледају природно. Ево како изгледа наш програм:
new Repository(@"C:\path\to\repo").Head.Tip.Message;
За десктоп Виндоуз апликације, постоји чак и NuGet пакет који ће вам помоћи да брзо почнете.
objective-git
Ако се ваша апликација извршава на Епл платформи, највероватније користите Objective-C као свој језик имплементације. Objective-Git (https://github.com/libgit2/objective-git) је име Libgit2 везивања за то окружење. Пример програма изгледа овако:
GTRepository *repo =
[[GTRepository alloc] initWithURL:[NSURL fileURLWithPath: @"/path/to/repo"] error:NULL];
NSString *msg = [[[repo headReferenceWithError:NULL] resolvedTarget] message];
Objective-git у потпуности саражује са Swift, тако да се не морате плашити ако сте оставили Objective-C.
pygit2
Libgit2 везивања за Пајтон се називају Pygit2 и можете да их пронађете на адреси http://www.pygit2.org/. Наш пример програма:
pygit2.Repository("/path/to/repo") # open repository
.head # get the current branch
.peel(pygit2.Commit) # walk down to the commit
.message # read the message
Наставак читања
Наравно, потпуни третман Libgit2 могућности је ван опсега ове књиге. Ако желите више информација о самом Libgit2, на адреси https://libgit2.github.com/libgit2 постоји API документација, а скуп водича на адреси https://libgit2.github.com/docs. За остала везивања, проверите испоручени README и тестове; тамо често постоје мали туторијали и смернице за наставак читања.