Git
Chapters ▾ 2nd Edition

5.3 Дистрибуирани Гит - Одржавање пројекта

Одржавање пројекта

Осим што треба да знате како да ефикасно допринесете пројекту, вероватно ћете морати да научите и како да одржавате пројекат. Ово може да се састоји од прихватања и примењивања закрпа генерисаних са format-patch које су вам послате имејлом, или од интегрисања промена на удаљеним гранама за репозиторијуме које сте додали као удаљене свом пројекту. Било да одржавате канонички репозиторијум или желите да помогнете тако што ћете верификовати или одобравати закрпе, треба да знате како да прихватите рад на начин који је најпрегледнији и најјаснији осталим сарадницима и да можете да га одржавате на дуге стазе.

Рад са тематским гранама

Када размишљате о интегрисању новог рада, у општем случају је добра идеја да ствари прво испробате на тематској грани — привременој грани коју сте направили само због тестирања тог новог кода. На овај начин је лако унети појединачно мале измене у закрпу и оставити је ако не ради све док не будете имали времена да јој се посветите. Ако изаберете једноставно име гране засновано на теми рада који желите да пробате, као што је ruby_client или нешто подједнако описно, лако можете да га запамтите ако морате да је напустите на неко време, па да јој се касније вратите. Одржавалац Гит тежи да прави и простор имена за гране — као што је sc/ruby_client, где је sc скраћеница за особу која даје допринос. Као што се сећате, можете да направите гране базиране на master грани на следећи начин:

$ git branch sc/ruby_client master

Или, ако желите да одмах и скочите на њу, можете да искористите опцију checkout -b:

$ git checkout -b sc/ruby_client master

Сада сте спремни да додате допринети рад који сте примили у ову тематску грани и да одлучите да ли желите да га спојите у своју дуготрајну грану.

Примењивање закрпа из имејлова

Ако добијете закрпу преко мејла и треба да је интегришете у свој пројекат, закрпу треба да примените на тематску грану и да је процените. Постоје два начина да се примени закрпа коју сте добили путем имејла: са git apply или са git am.

Примењивање закрпе са apply

Ако сте добили закрпу од неког ко ју је генерисао командом git diff или неком варијацијом Јуниксове diff команде (што није препоручљиво, погледајте следећи одељак), можете да је примените git apply командом. Под претпоставком да сте закрпу сачували у /tmp/patch-ruby-client.patch, овако можете да је примените:

$ git apply /tmp/patch-ruby-client.patch

Ово мења фајлове у радном директоријуму. Скоро је идентично као и извршавање команде patch -p1 за примењивање закрпе, мада је више параноична и прихвата мање непотпуних подударања него patch. Обрађује и додавањем, брисањем и преименовањем фајлова у случају да је то описано у git diff формату, што patch неће да уради. Коначно, git apply је модел са принципом „примени све или одбаци све” где ће се или применити све или ништа, док patch може парцијално да примењује закрпе, остављајући радни директоријум у чудном стању. git apply је у целини посматрано много конзервативнији него patch. Неће креирати комит уместо вас — када га покренете, уведене промене морате ручно да стејџујете и комитујете.

git apply можете да употребите и да видите да ли ће се закрпа применити без проблема пре него што заправо пробате да је примените — само извршите git apply --check са закрпом:

$ git apply --check 0001-seeing-if-this-helps-the-gem.patch
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply

Ако нема излаза, то значи да би закрпа требало да се примени без проблема. У случају неуспеха ова команда такође враћа излазну вредност различиту од нуле, тако да је можете користити у скриптама ако желите.

Примењивање закрпе са am

Ако сарадник користи програм Гит и ако је био довољно искусан да за генерисање своје закрпе употреби команду format-patch, онда ће ваш посао бити много лакши јер закрпа садржи информације о аутору и комит поруку. Ако можете, саветујте своје сараднике да за генерисање закрпа које вам шаљу уместо diff користе format-patch. git apply би требало да користите само за старе закрпе и такве ствари.

Да бисте применили закрпу која је генерисана са format-patch, употребите git am. Технички, git am је створено да чита mbox фајлове; то су једноставни фајлови чистог текстуалног формата који служе за чување једне или више имејл порука у једном текстуалном фајлу. Изгледају отприлике овако:

From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] Add limit to log function

Limit log functionality to the first 20

Ово је почетак излаза команде format-patch коју сте управо видели у претходном одељку; а такође је и исправан mbox имејл формат. Ако вам је неко исправно послао имејл са закрпом користећи git send-email, a vi га преузмете u mbox формат, онда можете да усмерите git am на тај mbox фајл, и почеће да примењује све закрпе које види. Ако користите имејл клијент који може да чува неколико имејлова у mbox формату, можете да сачувате читаву серију закрпи у фајл, па да онда употребите git am над тим фајлом, а команда ће кренути да примењује све закрпе које пронађе у фајлу.

Међутим, ако је неко на систем за тикете или нешто слично окачио закрпу коју је генерисао са format-patch, можете локално да сачувате фајл, па да онда тај фајл који је сачуван на диску проследите команди git am да бисте га применили:

$ git am 0001-limit-log-function.patch
Applying: Add limit to log function

Као што видите, закрпа је примењена без проблема и аутоматски је креиран нови комит. Информације о аутору су узете из From и Date заглавља имејла, а порука комита је узета из Subject и тела (пре закрпе) имејла. На пример, ако је ова закрпа примењена из mbox примера изнад, генерисани комит би изгледао некако овако:

$ git log --pretty=fuller -1
commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Author:     Jessica Smith <jessica@example.com>
AuthorDate: Sun Apr 6 10:17:23 2008 -0700
Commit:     Scott Chacon <schacon@gmail.com>
CommitDate: Thu Apr 9 09:19:06 2009 -0700

   Add limit to log function

   Limit log functionality to the first 20

Информација Commit указује на особу која је применила закрпу и на време када је то учињено. Информација Author је особа која је првобитно направила закрпу и када.

Али може се догодити и да се закрпа не примени без проблема. Можда је ваша главна грана отишла предалеко од гране за коју је закрпа направљена, или закрпа зависи од неке друге закрпе коју још увек нисте применили. У том случају, git am процес неће успети и питаће вас шта желите да урадите:

$ git am 0001-see-if-this-helps-the-gem.patch
Applying: See if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Patch failed at 0001.
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".

Ова команда поставља маркере конфликта у све фајлове у којима постоје проблеми, слично као код конфликта при спајању или ребазирању. Проблем се такође решава на исти начин — уредите фајл тако да решите конфликт; затим стејџујете нови фајл, па покренете git am --resolved да се настави на следећу закрпу:

$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Applying: See if this helps the gem

Ако желите да програм Гит покуша мало интелигентније да реши конфликт, можете да му проследите опцију -3, што програму Гит налаже да проба троструко спајање. Ова опција подразумевано није укључена јер не функционише ако вам комит на коме закрпа каже да је базирана није у репозиторијуму. Ако имате тај комит — ако је закрпа базирана на јавном комиту — онда је у општем случају опција -3 много паметнија када се примењује закрпа са конфликтом:

$ git am -3 0001-see-if-this-helps-the-gem.patch
Applying: See if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.

У овом случају, без опције -3 би се закрпа сматрала за конфликт. Пошто је употребљена опција -3 закрпа се применила без проблема.

Ако примењујете неколико закрпа из mbox фајла, команду am можете да покренете и у интерактивном режиму, која стаје на свакој закрпи коју пронађе и пита вас желите ли да је примените:

$ git am -3 -i mbox
Commit Body is:
--------------------------
See if this helps the gem
--------------------------
Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all

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

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

Одјављивање удаљених грана

Ако је допринос послао Гит корисник који је подесио сопствени репозиторијум, гурнуо неки број промена на њега, па вам послао URL до репозиторијума и име удаљене гране у којој се налазе промене, можете да их додате као удаљени репозиторијум и локално урадите спајања.

Рецимо, ако је вам је Џесика послала мејл у коме каже да има одличну нову ствар у ruby-client грани свог репозиторијума, можете да је тестирате додавањем удаљеног репозиторијума и одјављивањем те гране локално:

$ git remote add jessica git://github.com/jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client

Ако вам касније пошаље још један имејл и са још једном граном са корисном могућности, могли бисте директно да одрадите fetch и checkout јер сте већ подесили удаљени репозиторијум.

Ово је најкорисније ако редовно радите са неком особом. Ако неко с времена на време даје допринос само једном закрпом, онда је прихватање преко мејла брже него захтевање да сви имају свој сервер и да сви стално додају и бришу удаљене репозиторијуме само да би добили неколико закрпа. Такође, мало је вероватно да желите да имате на стотине удаљених репозиторијума, сваки за неког ко допринесе само једну или две закрпе. Ипак, скрипте и хостинг сервиси могу ово да учине једноставнијим — зависи највише од тога како развијате програм и како то раде ваши сарадници.

Друга предност овог приступа је то што добијате и историју комитова. Мада можете да имате озбиљне проблеме са спајањем, знате где је у историји базиран њихов рад; право троструко спајање је подразумевано, тако да не морате да убацујете -3 и да се надате да је закрпа генерисана од јавног комита коме имате приступ.

Ако не радите редовно са особом, али ипак желите да повучете од њих на овај начин, git pull команди можете да наведете URL удаљеног репозиторијума. Ово један пут ради повлачење и не чува URL као удаљену референцу:

$ git pull https://github.com/onetimeguy/project
From https://github.com/onetimeguy/project
 * branch            HEAD       -> FETCH_HEAD
Merge made by the 'recursive' strategy.

Како утврдити шта је уведено

Сада имате тематску грану која садржи допринесен рад. У овом тренутку можете да одлучите шта ћете да радите са њим. Овај одељак се поново осврће на неколико команди како бисте видели како да их искористите да бисте видели тачно шта ћете урадити ако спојите ово у главну грану.

Често је корисно да добијете преглед свих комитова који су у овој грани али нису у вашој master грани. Додавањем --not опције испред имена гране можете да искључите комитове са master гране. Ово ради исту ствар као и master..contrib формат који смо користили раније. На пример, ако вам сарадник пошаље две закрпе и направите грану која се зове contrib, па примените те закрпе тамо, можете да извршите следеће:

$ git log contrib --not master
commit 5b6235bd297351589efc4d73316f0a68d484f118
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Oct 24 09:53:59 2008 -0700

    See if this helps the gem

commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
Author: Scott Chacon <schacon@gmail.com>
Date:   Mon Oct 22 19:38:36 2008 -0700

    Update gemspec to hopefully work better

Ако желите да видите које промене уводи сваки од комитова, сетите се да команди git log можете проследити опцију -p и она ће надовезати разлику која је уведена при сваком комиту.

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

$ git diff master

Ова команда вам приказује разлику, али може да вас завара. Ако се ваша master грана кретала унапред од када сте од ње направили тематску грану, онда ћете добити наизглед чудне резултате. Ово се дешава јер програм Гит директно пореди снимке последњег комита са тематске гране на којој се тренутно налазите и последњег комита master гране. На пример, ако сте додали линију у фајл на master грани, директно поређење снимака ће изгледати као да ће тематска грана да обрише ту линију.

Ако је master непосредни предак тематске гране, ово не представља проблем; али ако су две историје разишле, разлика ће изгледати као да додајете све нове ствари у тематску грану и бришете све што је јединствено у master грани.

Оно што уствари хоћете да видите су промене које су додате на тематској грани — рад који ћете увести ако спојите ову грану са master граном. То ћете постићи тако што ћете програму Гит наложити да упореди последњи комит на тематској грани са првим заједничким претком који тематска грана има са master граном.

Технички, то можете да урадите тако што ћете експлицитно одредити заједничког претка и онда покренути diff над њиме:

$ git merge-base contrib master
36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
$ git diff 36c7db

или сажетије:

$ git diff $(git merge-base contrib master)

Међутим, ниједно од ова два није посебно згодно за рад, па програм Гит нуди још једну скраћеницу којом радите исту ствар: синтаксу са три тачке. У контексту git diff команде, можете ставити три тачке после друге гране да бисте урадили diff између последњег комита гране на које се налазите и његовог заједничког претка са другом граном:

$ git diff master...contrib

Ова команда вам приказује само рад који уводи текућа тематска грана почевши од заједничког претка на master грани. То је веома корисна синтакса коју треба упамтити.

Интегрисање допринесеног рада

Када је сав рад на тематској грани спреман за интегрисање у главнију грану, поставља се питање како то извести. Сем тога, који свеобухватни процес рада желите да користите та одржавање свог пројекта? Имате пуно избора, па ћемо представити њих неколико.

Процеси рада са спајањем

Један од основних процеса рада је да просто спојите сав рад директно у своју master грану. У овом сценарију, имате master грану која у суштини садржи стабилан кôд. Када имате рад у тематској грани који вам се чини завршеним, или рад који је неко други допринео а ви сте га проверили, спајате га у своју master грану, па бришете ту управо спојену тематску грану и понављате процес.

На пример, ако имамо репозиторијум са радом у две гране које се зову ruby_client и php_client који изгледа као Историја са неколико тематских грана и прво спојимо ruby_client, па онда php_client, историја коју ћете на крају имати изгледа као После спајања тематске гране.

Историја са неколико тематских грана
Слика 72. Историја са неколико тематских грана
После спајања тематске гране
Слика 73. После спајања тематске гране

Ово је вероватно најједноставнији процес рада, али може да буде проблематичан ако радите на већим или стабилнијим пројектима где желите да буде јако обазриви око тога шта уводите.

Ако имате важнији пројекат, можда ћете желети да користите двофазни циклус спајања. У овом сценарију имате две дуготрајне гране, master и develop, у којима одређујете да се master ажурира само када се издвоји врло стабилно издање и сав нови кôд се интегрише у develop грану. Обе ове гране редовно гурате у јавни репозиторијум. Сваки пут када имате нову тематску грану коју треба спојити (Пре спајања тематске гране), спајате је у develop (Након спајања тематске гране); затим, када означите издање, master грану премотате унапред на место на којем се налази сада стабилна develop грана (Након издања пројекта).

Пре спајања тематске гране
Слика 74. Пре спајања тематске гране
Након спајања тематске гране
Слика 75. Након спајања тематске гране
Након издања пројекта
Слика 76. Након издања пројекта

Овако, када људи клонирају репозиторијум вашег пројекта, могу или да одјаве master да изграде последњу стабилну верзију и једноставно увек одржавају актуелну верзију, или могу да одјаве develop, која садржи најновији кôд. Овај концепт можете и да проширите тако да имате integrate грану у коју се сав рад спаја у једно. Онда, када кôд на тој грани постане стабилан и прође тестирање, спајате га у develop грану; и када се то на неко време покаже као стабилно, master грану премотате унапред.

Процеси рада са спајањем великих грана

Гит пројекат има четири дуготрајне гране: master, next и seen (раније се звала pu –- предложена ажурирања) за нови рад и maint за бекпортове одржавања. Када сарадници унесу нови рад, он се сакупља у тематске гране репозиторијума одржаваоца на начин сличан ономе што смо већ описали (погледајте Управљање комплексним низом тематских грана на које се даје допринос). У овом тренутку, теме се процењују да би се одредило да ли је безбедно да се употребе или још треба да се ради на њима. Ако су безбедне, спајају се у next, и та грана се гура како би сви могли да пробају интегрисане теме заједно.

Управљање комплексним низом тематских грана на које се даје допринос
Слика 77. Управљање комплексним низом тематских грана на које се даје допринос

Ако на темама још треба да се ради, спајање се обавља у seen. Када се одреди да су потпуно стабилне, теме се поново спајају у master. Затим се се поново изграђују гране next и seen од master гране. Ово значи да се master скоро увек креће унапред, next се с времена на време ребазира, а seen се још чешће ребазира.

Спајање тематских грана доприноса у дуготрајне гране за интеграцију
Слика 78. Спајање тематских грана доприноса у дуготрајне гране за интеграцију

Када се тематска грана коначно споји у master, она се брише из репозиторијума. Гит пројекат такође има и maint грану која се рачва из последњег издања да би се обезбедиле бекпортоване закрпе за случај да је потребно ново издање које само решава ситније проблеме а не укључује нови садржај (maintenance release). Зато, када клонирате Гит репозиторијум, имате четири гране које можете одјавити да сагледате пројекат у разним фазама развоја, зависно од тога колико стабилну верзију желите да имате, или како желите да дате допринос пројекту; а одржавалац има структурисан процес рада који им помаже око нових доприноса. Процес рада Гит пројекта је специјализован. Да бисте ово јасно разумели, погледајте водич за Гит одржаваоца.

Процеси рада са ребазирањем и одабиром (cherry-picking)

Други одржаваоци више воле допринесени рад ребазирају или одаберу (cherry-pick — од допринесеног селективно изаберу оно са највише користи) допринесен рад са врха своје master гране уместо да га споје у њу, како би одржали углавном линеарну историју. Када имате рад у тематским гранама и одлучили сте да желите да га интегришете, померате се на ту грану и покрећете команду за ребазирање да бисте поново изградили промене на врх текуће master гране (или develop гране, и тако даље). Ако то прође како треба, можете да премотате унапред своју master грану и завршићете са линеарном историјом пројекта.

Други начин да преместите уведени рад са једне гране на другу је да га одаберете. Одабирање (cherry-picking) је у програму Гит као ребазирање за један комит. Узима закрпу која је уведена комитом и покушава да је поново примени на грану на којој се тренутно налазите. Ово је корисно ако имате већи број комитова на тематској грани, а желите да интегришете само један од њих, или имате само један комит на тематској грани и више вам одговара да селективно изаберете само један од њих (да га одаберете) уместо да обавите ребазирање. На пример, претпоставимо да имате пројекат који изгледа овако:

Пример историје пре одабирања
Слика 79. Пример историје пре одабирања

Ako želite da povučete komit e43a6 u master granu, možete da извршите:

$ git cherry-pick e43a6
Finished one cherry-pick.
[master]: created a0a41a9: "More friendly message when locking the index fails."
 3 files changed, 17 insertions(+), 3 deletions(-)

Ово повлачи исту промену која је уведена у e43a6, али добијате нову SHA-1 вредност за комит, јер је датум примењивања другачији. Сада ваша историја изгледа овако:

Историја након одабира комита на тематској грани
Слика 80. Историја након одабира комита на тематској грани

Сада можете да обришете тематску грану и одбаците комитове које нисте желели да повучете.

Rerere

Ако радите пуно спајања и ребазирања, или одржавате дуготрајну тематску грану, програм Гит вам пружа могућност под именом „rerere” која може да помогне.

Rerere је скраћеница од „reuse recorded resolution” (поново искористи забележено решење) — то је начин да се скрати ручно решавање конфликта. Када је rerere укључено, програм Гит ће чувати скуп пре- и пост-слика успешних спајања, па ако примети да постоји конфликт који потпуно личи на неки који сте већ разрешили, онда ће искористити то решење од прошлог пута и неће вас замарати тиме.

Ова могућност долази у два дела: конфигурационо подешавање и команда. Конфигурационо подешавање је rerere.enabled и довољно је корисно да га ставите у глобална подешавања:

$ git config --global rerere.enabled true

Одсада, кад год урадите спајање које разрешава конфликте, решење ће бити забележено у кешу за случај да поново затреба у будућности.

Ако буде било потребе, командом git rerere можете да имате интеракцију са rerere кешом. Када се позове сама, програм Гит проверава своју базу података решења и покушава да пронађе подударање са било којим од тренутних конфликата при спајању и реши их (мада се ово ради аутоматски ако је rerere.enabled подешено на true). Постоје и подкоманде којима можете да видите шта ће бити забележено, да обришете одређено решење из кеша и да обришете цео кеш. Rerere ћемо детаљније описати у Rerere.

Означавање издања

Када одлучите да направите пресек и објавите ново издање, обично је добра идеја да доделите ознаку тако да бисте могли поново да креирате то издање у било ком каснијем тренутку. Нову ознаку можете направити онако како смо објаснили у Основе програма Гит. Ако одлучите да потпишете ознаку као одржавалац, означавање би могло да изгледа овако:

$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <schacon@gmail.com>"
1024-bit DSA key, ID F721C45A, created 2009-02-09

Ако потпишете своје ознаке, могли бисте имати проблем са дистрибуцијом јавног PGP кључа који се користи за потписивање ваших ознака. Одржавалац Гит пројекта решава овај проблем тако што укључује свој јавни кључ као блоб у репозиторијуму и онда додаје ознаку која директно показује на тај садржај. Да бисте урадили ово, можете одредити који кључ желите тако што ћете извршити gpg --list-keys:

$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
pub   1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
uid                  Scott Chacon <schacon@gmail.com>
sub   2048g/45D02282 2009-02-09 [expires: 2010-02-09]

Онда тај кључ можете директно да увезете у базу података програма Гит тако што ћете га извести и пајповати то кроз git hash-object, што пише нови блоб са тим садржајем у Гит и враћа вам SHA-1 блоба:

$ gpg -a --export F721C45A | git hash-object -w --stdin
659ef797d181633c87ec71ac3f9ba29fe5775b92

Сада када имате садржај свог кључа у програму Гит, можете да направите ознаку која показује директно на њега тако што ћете навести нову SHA-1 вредност коју вам је вратила команда hash-object:

$ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92

Ако извршите git push --tags, ознака maintainer-pgp-pub ће бити подељена са свима. Ако неко жели да потврди ознаку, може директно да увезе ваш PGP кључ тако што ће повући блоб директно из базе података и увести га у GPG:

$ git show maintainer-pgp-pub | gpg --import

Тај кључ може да се искористи за потврђивање свих ваших потписаних ознака. Такође, ако уз поруку ознаке прикључите и инструкције, извршавање git show <ознака> ће вам омогућити да крајњем кориснику издате одређенија упутства у вези потврђивања ознака.

Генерисање броја изградње

Пошто програм Гит нема монотону растуће бројеве као ’v123’ или нешто тако који ће ићи уз сваки комит, у случају да уз сваки комит желите и име читљиво за људе, можете да извршите git describe над тим комитом. Као одговор, програм Гит генерише стринг који се састоји од имена најближе ознаке раније од тог комита а, након којег следи број комита од те ознаке и на крају делимичну SHA-1 вредност комита који се описује (испред којег се наводи слово „g” са значењем Гит):

$ git describe master
v1.6.2-rc1-20-g8c5b85c

На овај начин можете да извезете снимак или изградњу и да му дате име које људима има смисла. Заправо, ако изградите програм Гит из изворног кода који сте клонирали из Гит репозиторијума, git --version вам даје нешто што изгледа овако. Ако описујете комит који сте директно обележили, једноставно вам даје име ознаке.

Команда git describe подразумевано захтева прибележене ознаке (ознаке креиране са заставицом -a или -s); ако желите и да користите предности једноставних ознака (које нису прибележене), команди додајте и опцију --tags. Овај стринг можете да користите и као одредиште за git checkout или git show команду, мада се она ослања на скраћену SHA-1 вредност са краја, тако да можда неће важити довека. На пример, Линукс кернел је недавно скочио са 8 на 10 карактера да би се обезбедила јединственост међу SHA-1 објекта, тако да су стари излази команде git describe постали неважећи.

Припрема за издање

Сада желите да објавите изградњу. Једна од ствари коју ћете желети да урадите јесте да креирате архиву последњег снимка свог кода за оне јадне душе које не користе програм Гит. Команда за то је git archive:

$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz

Ако неко отвори тај тарбол, добиће последњи снимак вашег пројекта у директоријуму project. Можете и да направите zip архиву на скоро исти начин, само што ћете команди git archive проследити опцију --format=zip:

$ git archive master --prefix='project/' --format=zip > `git describe master`.zip

Сада имате лепу тарбол и zip архиву издања свог пројекта коју можете поставити на свој веб сајт или послати имејлом другим људима.

Кратки лог

Време је да пошаљете имејл људима на вашој листи који желе да знају шта се дешава са вашим пројектом. Леп начин да брзо добијете неку врсту белешки промена (тзв. changelog) онога што је додато у пројекат од последњег издања или мејла је да употребите git shortlog команду. Она ће сумирати све комитове у опсегу који наведете; на пример, следећа команда ће вам дати кратак преглед свих комитова од последњег издања, ако се последње издање зове v1.0.1:

$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (8):
      Add support for annotated tags to Grit::Tag
      Add packed-refs annotated tag support.
      Add Grit::Commit#to_patch
      Update version and History.txt
      Remove stray `puts`
      Make ls_tree ignore nils

Tom Preston-Werner (4):
      fix dates in history
      dynamic version method
      Version bump to 1.0.2
      Regenerated gemspec for version 1.0.2

Добијате чист резиме свих комитова од верзије v1.0.1, груписане по аутору, који можете послати као имејл на своју листу.