Git
Chapters ▾ 2nd Edition

5.3 Distribuirani Git - Održavanje projekta

Održavanje projekta

Sem što treba da znate kako da efikasno doprinesete projektu, verovatno ćete morati da naučite i kako da ga održavate. Ovo može da se sastoji od prihvatanja i primenjivanja zakrpa generisane sa format-patch i poslate vama putem mejla, ili od integrisanja promena na udaljenim granama za repozitorijume koje ste dodali kao rimoutove svom projektu. Bilo da održavate kanoničan repozitorijum ili želite da pomognete tako što ćete verifikovati ili prihvatati zakrpe, treba da znate kako da prihvatite rad na način koji je najpregledniji drugim kontributorima i da možete da ga održavate na duge staze.

Rad sa tematskim granama

Kada razmišljate o integrisanju novog rada, u opštem slučaju je dobra ideja da stvari prvo isprobate na tematskoj grani — na trenutnoj grani koju ste napravili specifično radi testiranja da li novi delovi koda rade. Na ovaj način je lako uneti male izmene posebno u zakrpu i ostaviti je tako ako ne radi dok ne budete imali vremena da se kasnije posvetite njoj. Održavalac Git projekta neretko pravi i nejmspejs za grane — na primer sc/ruby_client, gde je sc skraćenica za osobu koja doprinosi radu. Kao što se sećate, možete da napravite grane bazirane na master grani na sledeći način:

$ git branch sc/ruby_client master

Ili, ako želite da odmah i skočite na nju, možete da iskoristite checkout -b opciju:

$ git checkout -b sc/ruby_client master

Sada ste spremni da dodate svoj doprinos ovoj tematskoj grani i da odlučite da li želite da je spojite u odgovarajuću dugotrajnu granu.

Primenjivanje zakrpa preko mejlova

Ako dobijete zakrpu preko mejla i treba da je integrišete u svoj projekat, treba da primenite zakrpu na tematsku granu i da je procenite. Postoje dva načina za primenjivanje zakrpe koju ste dobiji butem mejla: pomoću git apply ili git am.

Primenjivanje zakrpe sa apply

Ako ste dobili zakrpu od nekog ko ju je generisao sa git diff ili Juniksovom diff komandom (što nije preporučljivo, pogledajte sledeći odeljak), možete da je primenite git apply komandom. Pod pretpostavkom da ste sačuvati zakrpu na /tmp/patch-ruby-client.patch, možete da je primenite ovako:

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

Ovo modifikuje fajlove u radnom direktorijumu. Ovo je skoro identično kao i pokretanje patch -p1 komande za prihvatanje zakrpe, mada je više paranoična i prihvata manje nejasnijih parova nego patch. Rukuje i dodavanjem, brisanjem i preimenovanjem fajlova kako je opisano u git diff formatu, što patch neće da uradi. Konačno, git apply je model sa principom "primeni sve ili odbaci sve" gde će se ili primeniti sve ili ništa, dok patch može parcijalno da primenjuje zakrpe, ostavljajući radni direktorijum u čudnom stanju. git apply je i generalno mnogo konzervativniji nego patch. Neće kreirati komit umesto vas — kada ga pokrenete, morate da stejdžujete komit i ručno komitujete novonastale promene.

Možete da koristite git apply i da vidite da li će se zakrpa uklopiti kako valja pre nego što zapravo probate da je primenite — samo pokrenite git apply --check sa zakrpom:

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

Ako nema izlaza, to znači da će se zakrpa prihvatiti kako valja. Ova komanda takođe daje ne-nula izlaz u slučaju neuspeha, tako da možete da je koristite u skriptama ako želite.

Primenjivanje zakrpe sa am

Ako je kontributor korisnik Gita i ako je bio dovoljno dobar da iskoristi format-patch komandu da generiše svoju zakrpu, onda će vaš posao biti mnogo lakši jer zakrpa sadrži informacije o autoru i komit poruke. Ako možete, ohrabrujte svoje kontributore da korsite format-patch umesto diff za generisanje zakrpa koje vam šalju. Treba da morate da koristite git apply samo za legat zakrpe i takve stvari.

Da biste primenili zakrpu koja je generisana sa format-patch, koristite git am. Tehnički, git am je stvoren da čita mbox fajlove; to su jednostavni fajlovi običnog tekstualnog formata koji služe za čuvanje jedne ili više mejl poruka u jednom tekstualnom fajlu. Izgledaju nekako ovako:

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

Ovo je početak izlaza komande format-patch koju ste upravo videli u prethodnom odeljku. Ovo je takođe validan mbox mejl format. Ako vam je neko poslao mejl sa zakrpom koristeći git send-email, a vi skinete to u mbox format, onda možete da usmerite git am na taj mbox fajl, i počeće da primenjuje sve zakrpe koje vidi. Ako pokrenete mejl klijent koji može da čuva nekoliko mejlova u mbox formatu, možete da sačuvate čitavu seriju zakrpi u fajl i onda da iskoristite git am da ih primenjuje jednu po jednu.

Međutim, ako je neko okačio zakrpu koju je generisao sa format-patch na sistem za tikete ili nešto slično, možete da sačuvate fajl lokalno i onda da prosledite taj fajl koji je sačuvan na disku komandi git am da biste je primenili:

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

Kao što vidite, zakrpa je primenjena bez problema i automatski je kreiran novi komit. Informacije o autoru su uzete iz Form i Date hedera sa mejla, a poruka komita je iz Subject-a i tela (pre zakrpe) mejla. Na primer, ako je ova zakrpa primenjena sa mbox primera odozgo, generisani komit bi izgledao nekako ovako:

$ 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

Informacija Commit ukazuje na osobu koja je primenila zakrpu i na vreme kada je to učinjeno. Informacija Author je osoba koja je prvobitno napravila zakrpu i to vreme.

Ali moguće je i da se zakrpa ne primeni bez problema. Možda je glavna grana divergirala predaleko od grane za koju je zakrpa napravljena, ili zakrpa zavisi od druge zakrpe koju još uvek niste primenili. U tom slučaju, git am proces neće uspeti i pitaće vas šta želite da uradite:

$ git am 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing 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".

Ova komanda stavlja konfliktne markere u svim fajlovima sa kojima ima problema, slično kao kod konflikta pri spajanju ili rebaziranja. Problem se takođe rešava na isti način — editovanjem fajla da bi se rešio konflikt; zatim se stejdžuje novi fajl, i onda se pokrene git am --resolved da bi se krenulo na sledeću zakrpu:

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

Ako želite da Git proba da malo inteligentnije reši konflikt, možete da mu prosledite opciju -3, što tera Git da proba trostruki spoj. Ova opcija nije uključena po podrazumevanim podešavanjima jer ne radi ako vam komit na kome zakrpa kaže da je bazirana nije u repozitorijumu. Ako imate taj komit — ako je grana bazirana na javnom komitu — onda je opcija -3 generalno mnogo pametnija o primenjivanju zakrpe sa konfliktom:

$ git am -3 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing 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.

U ovom slučaju, ova zakrpa je već primenjena. Bez opcie -3, izgleda kao konflikt.

Ako primenjujete nekoliko zakrpa iz mbox-a, možete i da pokrenete am komandu u interaktivnom modu, koja staje na svakoj zakrpi koju pronađe i pita vas da li biste želeli da je primenite.

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

Ovo je lepo ako imate sačuvan poveći broj zakrpa, jer možete da vidite zakrpu prvo ako se ne sećate šta je u pitanju, ili da ne primenite zakrpu ako ste to već uradili.

Kada su sve zakrpe za vašu temu primenjene i komitovane na vašu granu, možete da izaberete da li ćete i kako da ih integrišete u dugotrajniju granu.

Čekautovanje udaljenih grana

Ako je doprinos došao od Git korisnika koji je podesio sopstven repozitorijum, gurnuo neki broj promena na njega, i onda vam poslao URL do repozitorijuma i ime udaljene grane na kojoj se nalaze promene, možete da ih dodate kao rimout i da uradite spojeve lokalno.

Recimo, ako je vam je Džesika poslala mejl u kome kaže da ima odličnu novu stvar u ruby-client grani svog repozitorijuma, možete da je testirate dodavanjem rimouta i čekautovanjem te grane lokalno:

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

Ako vam pošalje još jedan mejl kasnije i kaže vam da postoji još jedna grana sa korisnim stvarima, možete da ih pribavite i čekautujete jer već imate podešvanja za rimout.

Ovo je najkorisnije ako radite sa osobom konzistentno. Ako neko ima samo jednu zakrpu kojom doprinosi s vremena na vreme, onda je prihvatanje preko mejla brže nego zahtevanje da svi imaju svoj server i da svi kontinualno dodaju i brišu rimoutove da bi dobili nove zakrpe. Takođe, malo je verovatno da želite da imate na stotine rimoutova, svaki za nekog ko doprinese samo jednom ili dvaput. Ipak, skripte i hostovani servisi mogu ovo da učine jednostavnijim — zavisi najviše od toga kako razvijate program i kako vaši saradnici kodiraju.

Druga prednost ovog pristupa je to što dobijate i istoriju komitova. Mada možete da imate ozbiljne probleme sa spajanjem, znate gde je u istoriji baziran njihov rad; ispravan trostruki spoj je podrazumevani tako da ne morate da ubacujete -3 i da se nadate da je zakrpa generisana za javni komit kome imate pristup.

Ako ne radite sa osobom konzistentno, ali ipak želite da povučete sa njih na ovaj način, možete da navedete URL udaljenog repozitorijuma git pull komandi. Ovo radi jednovremeno povlačenje i ne čuva URL kao udaljenu referencu:

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

Kako utvrditi šta je uvedeno

Sada imate tematsku granu koja sadrži doprinesen rad. U ovom trenutku možete da odlučite šta ćete da radite sa njim. Ovaj odeljak se ponovo osvrće na nekoliko komandi kako biste videli kako da ih iskoristite da biste videli tačno šta ćete uraditi ako spojite ovo u glavnu granu.

Često je korisno da pogledate izveštaj svih komitova koji su u ovoj grani ali nisu na master grani. Možete da izbacite komitove sa master grane tako što ćete dodati --not ispred imena grane. Ovo radi istu stvar kao i master..contrib format koji smo koristili ranije. Na primer, ako vam kontributor pošalje dve zakrpe i napravite granu koja se zove contrib i primenite te zakrpe tamo, možete da pokrenete ovo:

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

    seeing if this helps the gem

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

    updated the gemspec to hopefully work better

Da biste videli koje promene svaki od komitova uvodi, setite se da možete da prosledite -p opciju komandi git log i onda ćete moći da vidite razliku koja je uvedena pri svakom komitu.

Da biste videli punu razliku onoga što bi se dogodilo ako biste spojili ovu tematsku granu sa drugom granom, možda ćete morati da upotrebite čudan trik da biste dobili ispravne rezultat. Razmislite o pokretanju ove komande:

$ git diff master

Ova komanda vam daje razliku, ali može da vas zavara. Ako se vaša master grana kretala napred od kada ste napravili tematsku granu od nje, onda ćete naizgled dobiti čudne rezultate. Ovo se dešava jer Git direktno poredi snimke poslednjeg komita sa tematske grane na kojoj ste sada i poslednjeg komita master grane. Na primer, ako ste dodali liniju u fajlu na master grani, direktno poređenje snimaka će izgledati kao da će tematska grana da obriše tu liniju.

Ako je master direktan predak tematske grane, ovo nije problem; ali ako su dve istorije divergirale, razlika će izgledati kao da dodajete sve nove stvari u tematsku granu i brišete sve jedinstveno master grani.

Ono što stvarno hoćete da vidite su promene koje su dodate na tematskoj grani — rad koji ćete uvesti ako spojite ovu granu sa master-om. To ćete uraditi tako što ćete reći Gitu da uporedi poslednji komit na tematskoj grani sa prvim zajedničkim pretkom koji ima sa master granom.

Tehnički, to možete da uradite tako što ćete eksplicitno naći zajedničkog pretka i onda pokrenuti diff nad time:

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

Međutim, ovo nije zgodno za rad, pa Git nudi još jednu skraćenicu kojom radite istu stvar: sintaksu sa tri tačke. U kontekstu diff komande, možete da stavite tri tačke posle druge grane da biste uradili diff između poslednjeg komita grane na koje se nalazite i njegovog zajedničkog pretka sa drugom granom:

$ git diff master...contrib

Ova komanda vam prikazuje samo rad koji je trenutna tematska grana uvela od zajedničkog pretka sa master-om. To je veoma korisna sintaksa koju treba upamtiti.

Integrisanje doprinesenog rada

Kada je sav rad na tematskoj grani spreman za integrisanje u glavniju granu, postavlja se pitanje kako izvesti to. Sem toga, koji sveobuhvatni tok rada želite da koristite na svom projektu? Imate puno izbora, pa ćemo pokriti nekoliko njih.

Tokovi rada sa spajanjem

Jedan jednostavan tok rada spaja vaš rad sa master granom. U ovom scenariju, imate master granu koja u suštini sadrži stabilan kod. Kada morate da radite sa tematskim granama koje ste vi napravili ili koje su plod nečijeg doprinosa a vi ste ih potvrdili, spajate ih u svoju master granu, brišete tematsku granu i onda nastavljate proces. Ako imamo repozitorijum sa radom u dve grane koje se zovu ruby_client i php_client koji izgleda kao Istorija sa nekoliko tematskih grana i spojimo ruby_client prvo pa onda php_client, istorija koju ćete na kraju imati izgleda kao Posle spajanja tematske grane.

Istorija sa nekoliko tematskih grana.
Figure 73. Istorija sa nekoliko tematskih grana
Posle spajanja tematske grane.
Figure 74. Posle spajanja tematske grane

Ovo je verovatno najjednostavniji tok rada, ali može da bude problematičan ako radite na većim ili stabilnijim projektima gde želite da bude jako obazrivi oko toga šta uvodite u izmene.

Ako imate važniji projekat, možda ćete želeti da koristite dvofazni ciklus spoja. U ovom scenariju, imate dve dugotrajne grane, master i develop, u kojima odlučujete da se master apdejtuje samo kada nastane veoma stabla situacija a sav novi kod se integriše u develop granu. Regularno gurate obe ove grane u javni repozitorijum. Svaki put kada imate novu tematsku granu koju treba spojiti (Before a topic branch merge.), spajate je u develop (After a topic branch merge.); onda, kada tagujete izdanje, premotate master na koje god mesto da se nalazi sada stablna develop grana ([merwf__e]).

Before a topic branch merge.
Figure 75. Before a topic branch merge.
After a topic branch merge.
Figure 76. After a topic branch merge.
After a topic branch release.
Figure 77. After a project release.

Ovako, kada ljudi kloniraju repozitorijum vašeg projekta, mogu ili da čekautuju master da bi izbildovali najstabliniju verziju i lako uvek imaju aktuelnu verziju, ili mogu da čekautuju develop, što je napredniji ali slabije testiran kod. Možete i da nastavite ovaj koncept, da imate integrate granu gde se sav rad spaja u jedno. Onda, kada kôd na toj grani postane stabilan i prođe testiranje, spajate ga na develop granu; i kada se to pokaže kao stabilno neko vreme, premotate master granu unapred.

Tokovi rada sa spajanjem velikih grana

Git projekat ima četiri dugotrajne grane: master, next i pu (predloženi apdejtovi) za novi rad i maint za bekportove za održavanje. Kada novi rad bude predstavljen od strane kontributorâ, on se skuplja u tematske grane u održavaocevom repozitorijumu na način sličan onome što smo već opisali. (pogledajte Managing a complex series of parallel contributed topic branches.). U ovom trenutku, teme se procenjuju da bi se odredilo da li je bezbedno da se uključe u glavni deo projekta ili još treba da se radi na njima. Ako su bezbedne, spajaju se u next, i ta grana se gura kako bi svi mogli da probaju integrisane teme zajedno.

Managing a complex series of parallel contributed topic branches.
Figure 78. Managing a complex series of parallel contributed topic branches.

Ako na temama još treba da se radi, spajanje se obavlja u pu. Kada bude bilo odlučeno da su potpuno stabilne, teme se ponovo spajaju sa master i onda se ponovo grade od tema koje su bile u next ali još nisu maturirale do master-a. Ovo znači da se master skoro uvek kreće napred, next se s vremena na vreme rebazira, a pu se često rebazira.

Merging contributed topic branches into long-term integration branches.
Figure 79. Merging contributed topic branches into long-term integration branches.

Kada se tematska grana konačno spoji sa master, ona se briše iz repozitorijuma. Git projekat takođe ima i maint granu koja se forkuje od poslednjeg izdanja da bi se obezbedile bekportovane zakrpe za slučaj da je potrebno novo izdanje koje samo rešava sitnije probleme a ne uključuje novi sadržaj (maintenance release). Zato, kada klonirate Git repozitorijum, imate četiri grane koje možete da čekautujete i da sagledate projekat u raznim fazama razvoja, u zavisnosti od toga koliko stabilnu verziju želite da imate i kako želite da doprinesete projektu; a održavalac je struktuisao tok rada tako da kritičko sagledavanje novih dorpinosa bude olakšano.

Tokovi rada sa rebaziranjem i čeripikovanjem

Drugi održavaoci preferiraju da rebaziraju ili čeripikuju (selektivno izaberu ono sa najviše beneficija od ponuđenog) doprinesen rad sa vrha master grane umesto da se spoje u njega, da bi održali uglavnom linearnu istoriju. Kada imate rad u tematskim granama i odlučili ste da želite da ga integrišete, pomerate se na tu granu i pokrećete komandu za rebaziranje da biste ponovo izgradili promene na trenutni vrh master grane (ili develop, i tako dalje). Ako to bude radilo kako treba, možete da premotate svoju master granu unapred, i dobićete linearnu istoriju projekta.

Drugi način da pomerite predstavljeni rad sa jedne grane na drugu je da čeripikujete. Čeripikovanje je u Gitu kao rebaziranje za jedan komit. Uzima zakrpu koja je uvedena u komit i pokušava da je ponvo primeni na granu na kojoj se trenutno nalazite. Ovo je korisno ako imate veći broj komitova na tematskoj grane a želite da integrišete samo jdan od njih, ili imate samo jedan komit na tematskoj grani i preferirate da selektivno izaberete samo jedan od njih (da ga čeripikujete) umesto da rebazirate. Na primer, pretpostavimo da imate projekat koji izgleda ovako:

Primer istorije pre čeripikovanja.
Figure 80. Primer istorije pre čeripikovanja.

Ako želite da povučete komit e43a6 u master granu, možete da pokrenete

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

Ovo povlači istu promenu koja je predstavljena u e43a6, ali dobijate novu SHA-1 vrenost za komit, jer je odgovarajući datum drugačiji. Sada istorija izgleda ovako:

Istorija nakon čeripikovanja komita na tematskoj grani.
Figure 81. Istorija nakon čeripikovanja komita na tematskoj grani.

Sada možete da obrišete tematsku granu i odbacite komitove koje niste želeli da povučete.

Rerere

Ako radite puno spajanja i rebaziranja, ili održavate dugotrajnu tematsku granu, Git ima nešto što se zove "rerere" što može da pomogne.

Rerere je skraćenica od reuse recorded resolution (ponovo iskoristi zabeleženo rešenje) — to je način da se skrati ručno rešavanje konflikta. Kada je rerere uključen, Git će čuvati skup pre- i post-slika od uspešnih spojeva, i ako primeti da postoji konflikt koji liči na neki koji ste već razrešili, onda će iskoristiti rešenje od prošlog puta, i neće taj posao ostaviti vama.

Ovo svojstvo dolazi u dva dela: konfiguraciono podešavanje i komanda. Konfiguraciono podešavanje je rerere.enabled, i dovoljno je korisno da ga stavite u globalna podešvanja:

$ git config --global rerere.enabled true

Sad, kad god uradite spoj za koji rešite konflikt, rešenje će biti zabeleženo u kešu za slučaj da vam ponovo zatreba u budućnosti.

Ako bude bilo potrebene, možete da interagujete sa rerere kešom koristeći git rerere komandu. Kada se pozove sama, Git proverava bazu podataka rešenja i pokušava da nađe pogodak sa bilo kojim od trenutnih konflikata pri spoju i reši ih (mada se ovo radi automatski ako je rerere.enabled podešeno na true). Postoje i podkomande kojima možete da vidite šta će biti zabeleženo, da obrišete određeno rešenje iz keša i da obrišete ceo keš. Detaljnije ćemo preći rerere u Rerere.

Tagovanje izdanja

Kada ste odlučili da napravite presek i napravite novo izdanje, verovatno je dobra ideja da ostavite tag kako biste mogli da opet kreirate to izdanje u bilo kom trenutku nadalje. Novi tag možete napraviti onako kako smo objasnili u Osnove Gita. Ako odlučite da potpišete tag kao održavalac, tagovanje će možda izgledati ovako:

$ 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

Ako potpišete svoje tagove, možda ćete imati problem sa distribucijom javnog PGP ključa koji se koristi za potpisivanje tagova. Održavalac Git projekta rešava ovaj problem tako što uključuje svoj javni ključ kao blob u repozitorijumu i onda dodaje tag koji pokazuje direktno na taj sadržaj. Da biste uradili ovo, možete da otkrijete koji ključ želite tako što ćete pokrenuti 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]

Onda možete direktno da importujete ključ u Gitovu bazu podataka tako što ćete ga eksportovati i pajpovati ga kroz git hash-object, što piše novi blob sa tim sadržajem u Git i natrag vam daje SHA-1 bloba:

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

Sada kada imate sadržaj svog ključa u Gitu, možete da napravite tag koji pokazuje direktno na njega zako što ćete specificirati novu SHA-1 vrednost koju vam je dala komanda hash-object:

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

Ako pokrenete git push --tags, tag maintainer-pgp-pub će biti podeljen sa svima. Ako neko želi da verifikuje tag, može da direktno importuje vaš PGP ključ tako što će povući blob direktno sa baze podataka i importovati ga u PGP:

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

Taj ključ može biti iskorišćen za verifikovanje svih vaših potpisanih tagova. Takođe, ako priključite instrukcije u tag poruci, pokretanje git show <tag> će dati krajnjem korisniku specifičnije instrukcije oko verifikacije tagova.

Generisanje bild broja

Pošto Git nema monotonu inkrementaciju brojeva kao v123 ili ekvivalent koji će ići uz svaki komit, ako želite da imate ime čitljivo za ljude uz svaki komit, možete da pokrenete git describe nad tim komitom. Git vam daje ime najbližeg taga sa brojem komitova navrh tog taga i delimičnu SHA-1 vrednost komita koji opisujete:

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

Na ovaj način možete da eksportujete snimak ili bild i imenujete ga na način razumljiv ljudima. Zapravo, ako bildujete Git preko izvornog koda koji ste klonirali iz Git repozitorijuma, git --version vam daje nešto što izgleda ovako. Ako opisujete komit koji ste direktno tagovali, daje vam ime taga.

Komanda git describe favorizuje pribeležene tagove (tagove kreirane sa -a ili -s zastavicom), pa bi tagove izdanja trebalo kreirati na ovaj način ako koristite git describe, da biste bili sigurni da je komit nazvan dobro kada bude opisan. Možete da koristite ovaj string i kao odredište za checkout ili show komande, mada se oslanja na skraćenu SHA-1 vrednost sa kraja, tako da možda neće važiti doveka. Na primer, Linuks kernel je skoro skočio sa 8 na 10 karaktera da bi se postarao da postoji jedinstvenost među SHA-1 objektima, tako da su stari izlazi komande git describe nevažeći.

Priprema za izdanje

Sada želite da izdate bild. Jedna od stavati koju ćete želeti da uradite jeste da kreirate arhivu poslednjeg snimka svog koda za one jadne duše koje koriste Git. Komanda koja vam ovo radi jeste git archive:

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

Ako neko otvori taj tarbol, dobiće poslednji snimak vašeg projekta pod direktorijumom projekta. Možete i da napravite zip arhivu na isti način, samo što ćete proslediti opciju --format=zip komandi git archive:

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

Sada imate lepu tarbol i zip arhivu izdanja svog projekta koju možete objaviti na svom sajtu ili poslati putem mejla drugim ljudima.

Kratki log

Vreme je da pošaljete mejl ljudima na vašoj listi koji žele da znaju šta se dešava sa vašim projektom. Dobar način da brzo dobijete neku vrstu beleški promena (tzv. changelog) za ono što je dodato u projekat od poslednjeg izdanja ili mejla je da koristite git shortlog komandu. Ona će sumirati sve komitove u dometu koji specificirate; na primer, sledeća komanda će vam dati kratak pregled svih komitova od poslednjeg izdanja, ako se poslednje izdanje zove 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

Dobijate čist rezime svih komitova od verzije v1.0.1, grupisane po autoru, koji možete poslati kao mejl svojoj listi.