Git
Chapters ▾ 2nd Edition

7.12 Гит алати - Паковање

Паковање

Мада смо представили уобичајене начине за пренос Гит података преко мреже (HTTP, SSH, итд.), постоји уствари још један начин за то који се не користи тако често, али ипак може бити прилично користан.

Програм Git је способан да своје податке „пакује” у један једини фајл. То може да се искористи у разним ситуацијама. Можда вам мрежа не ради, а промене морате да пошаљете својим сарадницима. Можда радите негде ван радног места и из разлога безбедности немате приступ локалној мрежи. Можда се управо покварила ваша бежична/етернет картица. Можда тренутно немате приступ дељеном серверу, неком хоћете да пошаљете ажурирања имејлом, али не желите да преносите 40 комитова путем format-patch.

У оваквим ситуацијама вам у помоћ стиже git bundle команда. Команда bundle ће запаковати све што би се иначе гурнуло кроз жицу git push комадом у бинарни фајл који некоме можете да пошаљете имејлом или да га ставите на флеш драјв, који затим распакујете у други репозиторијум.

Хајде да погледамо једноставан пример. Рецимо да имате репозиторијум са два комита:

$ git log
commit 9a466c572fe88b195efd356c3f2bbeccdb504102
Author: Scott Chacon <schacon@gmail.com>
Date:   Wed Mar 10 07:34:10 2010 -0800

    Second commit

commit b1ec3248f39900d2a406049d762aa68e9641be25
Author: Scott Chacon <schacon@gmail.com>
Date:   Wed Mar 10 07:34:01 2010 -0800

    First commit

Ако некоме желите да пошаљете тај репозиторијум, а немате право гурања на циљни репозиторијум, или једноставно не желите да га подесите, можете да га запакујете са git bundle create.

$ git bundle create repo.bundle HEAD master
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 441 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)

Сада имате фајл под именом repo.bundle који садржи све податке потребне да се поново креира master грана репозиторијума. У команди bundle морате да наведете сваку референцу или одређени опсег комитова који желите да буду део пакета. Ако имате намеру да се ово клонира негде другде, требало би да додате и HEAD као референцу, као што смо ми овде урадили.

Овај repo.bundle фајл можете да пошаљете имејлом неком другом, или да га прекопирате на USB драјв и однесете га.

С друге стране, рецимо да је вама послат овај repo.bundle фајл и да желите да радите на пројекту. Можете да клонирате из бинарног фајла у директоријум, исто као што бисте и са URL адресе.

$ git clone repo.bundle repo
Cloning into 'repo'...
...
$ cd repo
$ git log --oneline
9a466c5 Second commit
b1ec324 First commit

Ако HEAD не укључите у референце, морате такође да наведете -b master или која год грана да је укључена у фајл, јер у супротном програм неће знати коју грану да одјави.

Рецимо да сада направите три комита на њој и нове комитове желите да пошаљете назад пакетом на USB драјву или имејлом.

$ git log --oneline
71b84da Last commit - second repo
c99cf5b Fourth commit - second repo
7011d3d Third commit - second repo
9a466c5 Second commit
b1ec324 First commit

Најпре морамо да одредимо опсег комитова које желимо да запакујемо. За разлику од мрежних протокола који уместо нас одређују минимални скуп података који треба пренети преко мреже, ово ћемо морати ручно да одредимо. Истина да бисте могли једноставно да урадите исту ствар и запакујете комплетан репозиторијум, што би радило, али је боље да запакујете само разлике - само три комита које смо управо креирали локално.

Да бисте то урадили, мораћете да израчунате разлику. Као што смо описали у Опсези комитова, опсег комитова можете навести на разне начине. Да бисте добили три комита које имамо у нашој мастер грани, а који нису били у грани коју смо првобитно клонирали, можемо употребити нешто као што је origin/master..master или master ^origin/master. То можете да тестирате log командом.

$ git log --oneline master ^origin/master
71b84da Last commit - second repo
c99cf5b Fourth commit - second repo
7011d3d Third commit - second repo

Дакле, сада када имамо листу комитова које желимо да запакујемо, хајде да то и урадимо. Команди git bundle create треба да наведете име фајла пакета и опсег комитова који желите да запакујете.

$ git bundle create commits.bundle master ^9a466c5
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), 775 bytes, done.
Total 9 (delta 0), reused 0 (delta 0)

Сада у нашем директоријуму имамо фајл commits.bundle. Ако га пошаљемо партнеру, она може да га увезе у оригинални репозиторијум, чак и ако је тамо у међувремену урађено још посла.

Када прими пакет, она може да га испита и сазна шта се у њему налази пре него што га увезе у свој репозиторијум. Прва команда је bundle verify команда која ће проверити да ли је фајл исправан Гит пакет и да имате све неопходне претке потребне да се исправно састави.

$ git bundle verify ../commits.bundle
The bundle contains 1 ref
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
The bundle requires these 1 ref
9a466c572fe88b195efd356c3f2bbeccdb504102 Second commit
../commits.bundle is okay

Да је особа која је направила пакет запаковала само два последња комита која је направила, уместо сва три, оригинални репозиторијум не би био у стању да га увезе, јер му недостаје потребна историја. Тада би verify команда изгледала овако:

$ git bundle verify ../commits-bad.bundle
error: Repository lacks these prerequisite commits:
error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 Third commit - second repo

Међутим, наш први пакет је исправан, па из њега можемо да преузмемо комитове. Ако желите да видите гране у пакету које могу да се увезу, постоји и команда која приказује само главе:

$ git bundle list-heads ../commits.bundle
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master

Поткоманда verify ће вам такође приказати главе. Поента је да се види шта може да се повуче, тако да можете употребити fetch или pull команду и увезете комитове из овог пакета. Овде ћемо преузети ’master’ грану пакета у грану под именом ’other-master’ у нашем репозиторијуму:

$ git fetch ../commits.bundle master:other-master
From ../commits.bundle
 * [new branch]      master     -> other-master

Сада можемо видети да увезене комитове имамо на ’other-master’ грани, као и евентуалне комитове које смо у међувремену направили на својој ’master’ грани.

$ git log --oneline --decorate --graph --all
* 8255d41 (HEAD, master) Third commit - first repo
| * 71b84da (other-master) Last commit - second repo
| * c99cf5b Fourth commit - second repo
| * 7011d3d Third commit - second repo
|/
* 9a466c5 Second commit
* b1ec324 First commit

Дакле, git bundle може бити веома корисна за дељење или обављање мрежних операција када немате праву мрежу или дељени репозиторијум који вам то омогућавају.