Git
Chapters ▾ 2nd Edition

5.2 Distribuirani Git - Prispevanje projektu

Prispevanje projektu

Glavna težava z opisovanjem, kako prispevati projektu je, da obstaja veliko število spremenljivk, kako je to narejeno. Ker je Git zelo fleksibilen, ljudje lahko in tudi res delajo skupaj na mnoge načine in problematično je opisovati, kako bi morali prispevati - vsak projekt je nekoliko drugačen. Nekatere spremenljivke vključene so število aktivnih ljudi, ki prispevajo, izbrani potek dela, vaš dostop pošiljanja in možno zunanja metoda prispevanja.

Prva spremenljivka je število aktivnih ljudi, ki prispevajo - koliko uporabnikov aktivno prispeva kodo temu projektu in kako pogosto? V mnogih primerih boste imeli dva ali tri razvijalce z nekaj pošiljanj na dan ali možno manj za projekte v nekako mirnem stanju. Za večja podjetja ali projekte bi lahko število razvijalcev bilo v tisočih, s stotinami ali tisoči pošiljanj, ki prihajajo vsak dan. To je pomembno, ker z več in več razvijalci naletite na več težav kako zagotavljati, da vaša koda uporablja čistočo ali je enostavno združljiva. Spremembe, ki jih pošljete lahko postanejo zastarele ali precej polomljene z delom, ki je bilo združeno medtem ko ste delali ali medtem ko vaše spremembe čakajo na odobritev ali uporabo. Kako lahko obdržite vašo kodo konsistentno posodobljeno in vaša pošiljanja veljavna?

Naslednja spremenljivka je potek dela v uporabi za projekt. Je centralizirano z vsakim razvijalcem, ki ima enak dostop pisanja v glavno linijo kode? Ali ima projekt vzdrževalca ali integracijskega upravitelja, ki preveri vse popravke? So vsi popravki pregledani na stikih in odobreni? Ali ste vključeni v ta proces? Ali je sistem poročnika na mestu in ali jim morate poslati vaše delo prvotno?

Naslednja težava je vaš dostop pošiljanja. Potek dela, ki je zahtevan za prispevanje projektu je veliko bolj drugačen, če imate dostop pisanja k projektu, kot če ga nimate. Če nimate dostopa za pisanje, kako ima projekt raje, da sprejme prispevano delo? Ali ima politiko? Koliko dela prispevate na določen čas? Kako pogosto prispevate?

Vsa ta vprašanja lahko vplivajo, kako efektivno prispevati projektu in katere poteke dela imate raje ali so na voljo za vas. Pokrili bomo aspekte za vsakega od teh v seriji primerov uporabe in se premaknili od enostavnega do bolj kompleksnega; morali bi biti sposobni skonstruirati določen potek dela, ki ga potrebujete v praksi iz teh primerov.

Smernice pošiljanja

Preden pričnemo gledati določen primer uporabe, je tu hitro obvestilo o sporočilih pošiljanja. Imeti dobre smernice za ustvarjanje pošiljanj in se jih držati naredi delo z Git-om in sodelovanjem z ostalimi veliko enostavnejše. Projekt Git ponuja dokument, ki začrta število dobrih nasvetov za ustvarjanje pošiljanj iz katerih se pošlje popravke - to lahko preberete v izvorni kodi Git v datoteki Documentation/SubmittingPatches.

Najprej ne želite poslati kakršnih koli napak praznih znakov. Git ponuja enostaven način, da to preverite - preden pošljete, poženite git diff --check, ki identificira vse možne napake praznih znakov in jih izpiše za vas.

Output of `git diff --check`.
Figure 57. Output of git diff --check.

Če poženete ta ukaz preden pošljete, lahko poveste, če ste tik preden, da pošljete težave s praznimi znaki, ki lahko nagajajo ostalim razvijalcem.

Naslednej poskusite narediti vsako pošiljanje logično ločen skupek sprememb. Če lahko, poskusite narediti vaše spremembe prebavljive - ne kodirajte cel vikend na petih različnih težavah in nato pošljite vse kot eno masovno pošiljanje v ponedeljek. Tudi če ne pošljete med vikendom, uporabite vmesno fazo v ponedeljek, da se loči vaše delo v vsaj eno pošiljanje na težavo z uporabnim sporočilom na pošiljanje. Če nekatere spremembe spremenijo isto datoteko, poskusite uporabiti git add --patch za delno vmesne datoteke (pokrito v podrobnostih v Interactive Staging). Posnetek projekta pri nasvetu veje je identičen, če naredite eno pošiljanje ali pet, dokler so spremembe dodane na neki točki, torej poskusite narediti stvari enostavnejše za vaše kolege sodelavce, ko bodo morali pregledati vaše spremembe. Ta pristop tudi naredi enostavnejše potegniti ali povrniti eno izmed skupka sprememb, če to kasneje potrebujete. Rewriting History opisuje število uporabnih trikov Git za prepisovanje zgodovine in interaktivno dajanje datotek v vmesno fazo - uporabite ta orodja, da pomagajo izdelati čisto in razumljivo zgodovino preden pošljete delo nekomu drugemu.

Zadnja stvar za pomniti je sporočilo pošiljanja. Navaditi se ustvarjati kvalitetna sporočila pošiljanj naredi uporabo in sodelovanje z Git-om veliko enostavnejše. Kot splošno pravilo, bi se vaša sporočila morala začeti z eno vrstico, ki ni večja od 50 znakov in opisuje skupek sprememb jedrnato ter ji nato sledi prazna vrstica, ki ji sledi bolj podrobna razlaga. Projekt Git zahteva, da bolj podrobna razlaga vključuje vašo motivacijo za spremembe in kontrast njihove implementacije s prejšnjim obnašanjem - to je tudi dobra smernica za slediti. Dobra ideja je tudi uporabiti nujno prisotnos sedanjika v teh sporočilih. Z drugimi besedami, uporabite ukaze. Namesto “I added tests for” ali “Adding tests for,” uporabite “Add tests for.” Tu je predloga, ki jo je prvotno napisal Tim Pope:

Short (50 chars or less) summary of changes

More detailed explanatory text, if necessary.  Wrap it to
about 72 characters or so.  In some contexts, the first
line is treated as the subject of an email and the rest of
the text as the body.  The blank line separating the
summary from the body is critical (unless you omit the body
entirely); tools like rebase can get confused if you run
the two together.

Further paragraphs come after blank lines.

  - Bullet points are okay, too

  - Typically a hyphen or asterisk is used for the bullet,
    preceded by a single space, with blank lines in
    between, but conventions vary here

Vsa vaša sporočila pošiljanj izgledajo nekako takole, stvari so veliko enostavnejše za vas in razvijalce s katerimi delate. Git projekt ima dobro oblikovana sporočila pošiljanj - poskusite tam pognati git log --no-merges, da vidite, kako izgleda lepo oblikovana zgodovina pošiljanj projekta.

V naslednjem primeru in skozi večino te knjige zaradi kratkosti ta knjiga nima lepo oblikovanih sporočil, kot je ta; namesto tega, uporabljamo opcijo -m za git commit. Naredite kot pravimo in ne kot kot mi delamo.

Privatna majhna ekipa

Najenostavnejša nastavitev, na katero boste verjetno naleteli je privatni projekt z enim ali dvema razvijalcema. “Private” v tem kontekstu pomeni zaprto kodo - ni dostopna za zunanji svet. Vi in ostali razvijalci imate vsi dostop potiskanja v repozitorij.

V tem okolju lahko sledite poteku dela, ki je podoben čemur ste morda delali, ko ste uporabljali Subversion ali drug centraliziran sistem. Še vedno dobite prednosti stvari kot so pošiljanje brez povezave in prostrano enostavno razvejanje in združevanje vendar potek dela je lahko zelo podoben; glavna razlika je, da se združevanje zgodi na strani klienta namesto na strežniku v času pošiljanja. Poglejmo, kako lahko izgleda, ko dva razvijalca začneta delati skupaj z deljenim repozitorijem. Prvi razvijalec, John, klonira repozitorij, naredi spremembe in jih pošlje lokalno. (Sporočila protokola so bila zamenjana z ... v teh primerih, da jih nekako skrajšajo.)

# John's Machine
$ git clone john@githost:simplegit.git
Initialized empty Git repository in /home/john/simplegit/.git/
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'removed invalid default value'
[master 738ee87] removed invalid default value
 1 files changed, 1 insertions(+), 1 deletions(-)

Drug razvijalec, Jessica, naredi isto stvar - klonira repozitorij in pošlje spremembo:

# Jessica's Machine
$ git clone jessica@githost:simplegit.git
Initialized empty Git repository in /home/jessica/simplegit/.git/
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'add reset task'
[master fbff5bc] add reset task
 1 files changed, 1 insertions(+), 0 deletions(-)

Sedaj Jessica potisne njeno delo na strežnik:

# Jessica's Machine
$ git push origin master
...
To jessica@githost:simplegit.git
   1edee6b..fbff5bc  master -> master

John tudi poskuša potisniti svojo spremembo:

# John's Machine
$ git push origin master
To john@githost:simplegit.git
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'john@githost:simplegit.git'

John-u ni dovoljeno potisniti, ker je vmes potisnila Jessica. To je posebej pomembno za razumeti, če ste vajeni Subversion-a, ker boste opazili, da dva razvijalca nista uredila iste datoteke. Čeprav Subversion avtmoatično naredi to združevanje na strežniku, če so urejene različne datoteke, morate v Git-u združevati pošiljanja lokalno. John mora ujeti spremembe Jessice in jih združiti preden mu je dovoljeno potiskati:

$ git fetch origin
...
From john@githost:simplegit
 + 049d078...fbff5bc master     -> origin/master

Na tej točki John-ov lokalni repozitorij izgleda nekako takole:

John’s divergent history.
Figure 58. John’s divergent history.

John ima referenco na spremembe, ki jih je potisnila Jessica, vendar jih mora združiti v svoje delo preden mu je dovoljeno potisniti:

$ git merge origin/master
Merge made by recursive.
 TODO |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

Združevanje gre gladko - John-ova zgodovina pošiljanja sedaj izgleda nekako takole:

John’s repository after merging `origin/master`.
Figure 59. John’s repository after merging origin/master.

Sedaj lahko John testira svojo kodo, da zagotovi, da še vedno ustrezno deluje in nato lahko potisne svoje novo združeno delo na strežnik:

$ git push origin master
...
To john@githost:simplegit.git
   fbff5bc..72bbc59  master -> master

Končno, John-ova zgodovina pošiljanja izgleda nekako takole:

John’s history after pushing to the `origin` server.
Figure 60. John’s history after pushing to the origin server.

Vmes je Jessica delala na tematski veji. Ustvarila je tematsko vejo imenovano issue54 in naredila tri pošiljanja na tej veji. Ni pa še ujela sprememb John-a, zato njena zgodovina pošiljanja izgleda nekako takole:

Jessica’s topic branch.
Figure 61. Jessica’s topic branch.

Jessica se želi sinhronizirati z John-om, torej ujame:

# Jessica's Machine
$ git fetch origin
...
From jessica@githost:simplegit
   fbff5bc..72bbc59  master     -> origin/master

To potegne delo, ki ga je vmes John potisnil. Zgodovina Jessice sedaj izgleda takole:

Jessica’s history after fetching John’s changes.
Figure 62. Jessica’s history after fetching John’s changes.

Jessica misli, da je njena tematska veja pripravljena, vendar želi vedeti, kaj mora združiti v njeno delo, da lahko potisne. Požene git log, da ugotovi:

$ git log --no-merges issue54..origin/master
commit 738ee872852dfaa9d6634e0dea7a324040193016
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 16:01:27 2009 -0700

   removed invalid default value

Sintaksa issue54..origin/master je dnevniški filter, ki vpraša Git, da prikaže samko seznam pošiljanj, ki so na kasnejši veji (v tem primeru origin/master), ki niso na prvi veji (v tem primeru issue54). Skozi to sintakso bomo šli v podrobnosti v Commit Ranges.

Za sedaj, lahko vidimo izpis, da je eno pošiljanje, ki ga je naredil John in ga Jessica ni združila. Če Jessica združi origin/master, je to eno pošiljanje, ki bo spremenilo njeno lokalno delo.

Sedaj Jessica lahko združi njeno tematsko delo v njeno lokalno vejo, združi, John-ovo delo (origin/master) v njeno vejo master in nato potisne nazaj na strežnik. Najprej preklopi nazaj na njeno master vejo, da integrira vso to delo:

$ git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.

Združi lahko najprej bodisi origin/master ali issue54 - obe sta nazvgor vodni, torej vrstni red ni pomemben. Zadnji posnetek bi moral biti identičen ne glede na vrstni red, ki ga izbere, samo zgodovina bo nekoliko drugačna. Najprej izbere združiti issue54:

$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
 README           |    1 +
 lib/simplegit.rb |    6 +++++-
 2 files changed, 6 insertions(+), 1 deletions(-)

Ne pride do nobenih problemov; kot lahko vidite je šlo za enostaven fast-forward. Sedaj Jessica združi delo John-a (origin/master):

$ git merge origin/master
Auto-merging lib/simplegit.rb
Merge made by recursive.
 lib/simplegit.rb |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Vse se združi čisto in zgodovina Jessice izgleda takole:

Jessica’s history after merging John’s changes.
Figure 63. Jessica’s history after merging John’s changes.

Sedaj je origin/master dosegljiv iz Jessicine veje master, da lahko uspešno potiska (ob predpostavki, da John vmes ni ponovno potisnil):

$ git push origin master
...
To jessica@githost:simplegit.git
   72bbc59..8059c15  master -> master

Vsak razvijalec je poslal nekajkrat in uspešno združil delo drug drugega.

Jessica’s history after pushing all changes back to the server.
Figure 64. Jessica’s history after pushing all changes back to the server.

To je eden najenostavnejših potekov dela. Delate nekaj časa, v splošnem na tematski veji in združite vašo vejo master, ko ste pripravljeni za integracijo. Ko želite deliti to delo, ga združite v vašo lastno vejo master, nato ujamite in združite origin/master, če se je spremenila in končno potisnite na vejo master na strežniku. Splošna sekvenca je nekaj takega:

General sequence of events for a simple multiple-developer Git workflow.
Figure 65. General sequence of events for a simple multiple-developer Git workflow.

Zasebne upravljane ekipe

V tem naslednjem scenariu, boste pogledali vloge prispevalcev v večji zasebni skupini. Naučili se boste, kako delati v okolju, kjer manjše skupine sodelujejo na lastnostih in nato so te prispevki na osnovi ekip integrirani s strani druge strani.

Recimo, da John in Jessica delata skupaj na lastnosti, medtem Jessica in Josie delata na drugi. V tem primeru podjetje uporablja tip poteka dela integracija-upravitelj, kjer je delo posameznih skupin integrirano samo od določenih inženirjev in veja master glavnega repozitorija je lahko posodobljena samo s strani teh inženirjev. V tem scenariju je vso delo narejeno na vejah na osnovi ekipi in potegnjene skupaj s strani integratorjev kasneje.

Sledimo poteku dela Jessice kot dela na njenih dveh lastnostih, sodeluje vzporedno z dvema različnima razvijalcema v tem okolju. Predpostavimo, da že ima njen repozitorij kloniran in se odloči delati najprej na featureA. Ustvari novo vejo za lastnost in naredi nekaj dela na njej:

# Jessica's Machine
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ vim lib/simplegit.rb
$ git commit -am 'add limit to log function'
[featureA 3300904] add limit to log function
 1 files changed, 1 insertions(+), 1 deletions(-)

Na tej točki potrebuje deliti nekaj dela z John-om torej potisne njena pošiljanja veje featureA na strežnik. Jessica nima dostopa potiskanja na vejo master - samo integratorji imajo - torej mora potisniti na drugo vejo, da lahko sodeluje z John-om:

$ git push -u origin featureA
...
To jessica@githost:simplegit.git
 * [new branch]      featureA -> featureA

Jessica sporoči po e-pošti Johnu, da je potisnila nekaj dela v vejo imenovano featureA in on lahko to sedaj pogleda. Medtem ko čaka za povratne informacije od John-a, se Jessica odloči začeti delati na featureB z Josie. Da začne, prične novo vejo lastnosti, ki je osnovana na strežniški veji master:

# Jessica's Machine
$ git fetch origin
$ git checkout -b featureB origin/master
Switched to a new branch 'featureB'

Sedaj, Jessica naredi nekaj pošiljanj na veji featureB:

$ vim lib/simplegit.rb
$ git commit -am 'made the ls-tree function recursive'
[featureB e5b0fdc] made the ls-tree function recursive
 1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'add ls-files'
[featureB 8512791] add ls-files
 1 files changed, 5 insertions(+), 0 deletions(-)

Jessicin repozitorij izgleda takole:

Jessica’s initial commit history.
Figure 66. Jessica’s initial commit history.

Pripravljena je potisniti njeno delo, vendar dobi e-pošto od Josie, da je veja z nekaj začetnega dela na njej že potisnjena na strežnik kot featureBee. Jessica najprej potrebuje združiti te spremembe v njeno lastno preden lahko potiska na strežnik. Nato lahko ujame spremembe Josie z git fetch:

$ git fetch origin
...
From jessica@githost:simplegit
 * [new branch]      featureBee -> origin/featureBee

Jessica lahko sedaj združi to v delo, ki ga je naredila z git merge:

$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by recursive.
 lib/simplegit.rb |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

Je pa manjši problem - potrebuje potisniti združeno delo v njeno vejo featureB v vejo featureBee na strežniku. To lahko naredi z določanjem lokalne veje, ki ji sledi podpičje (:), ki mu sledi oddaljena veja ukazu git push:

$ git push -u origin featureB:featureBee
...
To jessica@githost:simplegit.git
   fba9af8..cd685d1  featureB -> featureBee

To se imenuje refspec. Glejte The Refspec za bolj podrobno diskusijo respec Git-a in različnih stvari, ki jih lahko naredi z njimi. Opazite tudi zastavico -u7; to je kratica za --set-upstream, ki nastavi veje za enostavnejšo potiskanje in poteg kasneje.

Naslednje John pošlje e-pošto Jessici in ji pove, da je potisnil neke spremembe v vejo featureA in jo vpraša, če jih lahko potrdi. Požene git fetch, da potegne te spremembe:

$ git fetch origin
...
From jessica@githost:simplegit
   3300904..aad881d  featureA   -> origin/featureA

Nato lahko vidi, kaj je bilo sprememnjeno z git log:

$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 19:57:33 2009 -0700

    changed log output to 30 from 25

Končno združi delo John-a v njeno lastno vejo featureA:

$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
 lib/simplegit.rb |   10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)

Jessica želi nekaj prilagoditi, torej ponovno pošlje in nato potisne to nazaj na strežnik:

$ git commit -am 'small tweak'
[featureA 774b3ed] small tweak
 1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
   3300904..774b3ed  featureA -> featureA

Zgodovina pošiljanja Jessice sedaj izgleda nekako takole:

Jessica’s history after committing on a feature branch.
Figure 67. Jessica’s history after committing on a feature branch.

Jessica, Josie in John obvestilo integratorje, da sta veji featureA in featureBee na strežniku pripravljeni za integracijo v glavno linijo. Ko integratorji združijo te veje v glavno linijo, bo ujetje preneslo novo pošiljanje združevanja in naredilo zgodovino, da izgleda nekako takole:

Jessica’s history after merging both her topic branches.
Figure 68. Jessica’s history after merging both her topic branches.

Mnoge skupine preklopijo na Git zaradi te zmožnosti in imajo več ekip, ki delajo vzporedno, združujejo na različnih vrsticah dela kasneje v procesu. Zmožnost manjših podskupin ekipe, da sodelujejo preko oddaljenih vej brez potrebe po vključevanju ali oviri celotne ekipe je velika prednost Git-a. Sekvenca poteka dela, ki ste ga videli je nekaj takega:

Basic sequence of this managed-team workflow.
Figure 69. Basic sequence of this managed-team workflow.

Forkan javni projekt

Prispevanje javnim projektom je nekoliko drugačno. Ker nimate dovoljenja direktno posodobiti veje na projektu, morate nekako dati delo vzdrževalcem na nek drug način. Prvi primer opisuje prispevanje preko forkanja na Git gostiteljih, ki podpirajo enostavno forkanje. Mnogi strani gostiteljev to podpirajo (vključno GitHub, BitBucket, Google Code, repo.or.cz in ostali) in mnogi vzdrževalci projektov pričakujejo ta stil prispevanja. Naslednja sekcija se ukvarja s projekti, ki imajo raje sprejeti prispevane popravke preko e-pošte.

Najprej boste verjetno želeli klonirati glavni repozitorij, ustvariti tematsko vejo za popravek ali serijo popravkov, ki jih planirate prispevati in narediti delo tam. Sekvenca izgleda v osnovi takole:

$ git clone (url)
$ cd project
$ git checkout -b featureA
# (work)
$ git commit
# (work)
$ git commit
Note

Lahko boste želeli uporabiti rebase -i, da vaše delo stisnete v eno pošiljanje ali delo preuredite v pošiljanja, da naredite popravek enostavnejši za pregled razvijalcev - glejte Rewriting History za več informacij o interaktivnem ponovnem baziranju.

Ko je delo vaše veje končano in ste pripravljeni prispevati nazaj vzdrževalcem, pojdite na prvotno stran projekta in kliknite na gumb “Fork”, kar ustvari vaš lasten zapisljiv fork projekta. Nato morate dodati ta novi URL repozitorija kot drugo daljavo v tem primeru imenovano myfork:

$ git remote add myfork (url)

Nato morate potisniti vaše delo gor. Najenostavnejše je potisniti tematsko vejo, na kateri delate na vaš strežnik namesto združevanja v vašo vejo master in potiskanje tega navzgor. Razlog je, da če delo ni sprejeto ali je izbrano (cherry pick), vam ni treba previti nazaj vaše veje master. Če vzdrževalci združijo, ponovno bazirajo ali izberejo vaše delo, ga boste eventuelno kakorkoli dobili nazaj iz njihovega repozitorija:

$ git push -u myfork featureA

Ko je bilo vaše delo potisnjeno gor na vaš fork, morate obvestiti vzdrževalca. To je pogostokrat imenovano zahtevek potega in ga lahko ali generirate preko spletne strani - GitHub ima svoj lastni mehanizem zahtevkov potega, ki jih bomo obravnavali v GitHub - ali lahko poženete ukaz git request-pull in izpišete e-pošto vzdrževalcu projekta ročno.

Ukaz request-pull vzame osnovno vejo v katero želite potegniti vašo tematsko vejo in URL repozitorija Git, iz katerega želite potegniti ter izpisati povzetek vseh sprememb za katere sprašujete, da se jih potegne. Na primer, če Jessica želi poslati John-u zahtevek potega in je končala dve pošiljanji na tematski veji, ki jo je ravnokar potisnila, lahko požene tole:

$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
  John Smith (1):
        added a new function

are available in the git repository at:

  git://githost/simplegit.git featureA

Jessica Smith (2):
      add limit to log function
      change log output to 30 from 25

 lib/simplegit.rb |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

Izpis se lahko pošlje vzdrževalcu - pove jim, iz kje je delo razvejano, povzame pošiljanja in pove, od kje potegniti to delo.

Na projektu za katerega niste vzdrževalec, je v splošnem enostavnejše imeti vejo kot je master, ki vedno sledi origin/master in narediti vaše delo v tematskih vejah, ki jih lahko enostavno zavržete, če so zavrnjene. Imeti delovne teme izolirane v tematske veje, tudi naredi enostavnejše za vas, da ponovno bazirate vaše delo, če se je konica glavnega repozitorija vmes premaknila in vaša pošiljanja niso več uporabljena čisto. Na primer, če želite poslati drugo temo dela projekta, ne nadaljujte z delom na tematski veji, samo potisnite - pričnite znova iz veje glavnega repozitorija master:

$ git checkout -b featureB origin/master
# (work)
$ git commit
$ git push myfork featureB
# (email maintainer)
$ git fetch origin

Za sedaj vsaka od vaših tem je vsebovana znotraj silosa - podobno kot čakalna vrsta popravka - ki jo lahko prepišete in spremenite brez tem, ki se vmešavajo ali so soodvisne druga od druge, takole:

Initial commit history with `featureB` work.
Figure 70. Initial commit history with featureB work.

Recimo, da je vzdrževalec projekta povlekel veliko ostalih popravkov in poskusil vašo prvo vejo, vendar ne združuje več čisto. V tem primeru, lahko poskusite ponovno bazirati to vejo na vrh origin/master, rešite konflikte za vzdrževalca in nato ponovno pošljete vaše spremembe:

$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA

To prepiše vašo zgodovino, da sedaj izgleda kot Commit history after featureA work..

Commit history after `featureA` work.
Figure 71. Commit history after featureA work.

Ker ste vejo ponovno bazirali, morate določiti -f za vaš ukaz potiskanja, da lahko zamenjate vejo featureA na strežniku s pošiljanji, ki niso njihovi potomci. Alternativa bi bila potisniti to novo delo na različno vejo na strežniku (mogoče imenovano featureAv2).

Poglejmo še en bolj možen scenarij: vzdrževalec je pogledal delo v vaši drugi veji in mu je koncept všeč, vendar bi rad, da spremenite podrobnost implementacije. Tudi vzeli boste to priložnost, da premaknete delo, da bo osnovano na trenutni veji projekta master. Začnite novo vejo, ki je osnovana na trenutnu origin/master, tam stisnite spremembe featureB, rešite kakršnekoli konflikte, naredite implementacijo sprememb in nato to potisnite na novo vejo:

$ git checkout -b featureBv2 origin/master
$ git merge --squash featureB
# (change implementation)
$ git commit
$ git push myfork featureBv2

Opcija --squash vzame vso delo na združeni veji in jih stisne v en skupek sprememb, ki producira stanje repozitorija, kakor da bi se zgodilo realno združevanje, brez dejanskega združevanja pošiljanja. To pomeni, da bo vaše bodoče pošiljanje imelo samo enega starša in vam omogoča predstavitev vseh sprememb iz druge veje in nato naredite več sprememb pred snemanjem novega pošiljanja. Tudo opcija --no-commit je lahko uporabna za zakasnitev združevanja pošiljanja v primeru privzetega procesa združevanja.

Sedaj lahko pošljete vzdrževalcu sporočilo, da ste naredili zahtevane spremembe in te spremembe lahko najdejo v vaši veji featureBv2.

Commit history after `featureBv2` work.
Figure 72. Commit history after featureBv2 work.

Javni projekt preko e-pošte

Mnogi projekti so vzpostavili procedure za sprejemanje popravkov - preveriti boste morali določena pravila za vsak projekt, ker se razlikujejo. Odkar je na voljo nekaj starejših, večjih projektov, ki sprejemajo popravke preko razvijalskega e-poštnega seznama, bomo šli skozi primer tega sedaj.

Potek dela je podoben prejšnjemu primeru uporabe - ustvarite tematske veje za vsak popravek serije, na kateri delate. Razlika je, kako jih pošljete projektu. Namesto forkanja projekta in potiskanja v vašo lastno zapisljivo verzijo, generirate verzje e-pošte za vsako od serij pošiljanja in jih pošljete po e-pošti razvijalskemu e-poštnemu seznamu:

$ git checkout -b topicA
# (work)
$ git commit
# (work)
$ git commit

Sedaj imate dve pošiljanji, ki ju želite poslati na e-poštni seznam. Uporabili boste git format-patch, da generirate mbox oblikovane datoteke, ki jih lahko pošljete preko e-pošte na seznam - vsako pošiljanje pretvori v sporočilo e-pošte s prvo vrstico sporočila pošiljanja kot zadevo in preostanek sporočila plus popravek, ki ga pošiljanje predstavlja kot telo. Lepa stvar pri tem je, da uporaba popravka iz e-pošte generirane z format-patch ohrani vse informacije pošiljanja ustrezno.

$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch

Ukaz format-patch izpiše imena datotek popravka, ki jih ustvari. Preklop -M pove Git-u, da išče preimenovanja. Datoteke končno izgledajo takole:

$ cat 0001-add-limit-to-log-function.patch
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

Omejite dnevnik funkcionalnosti na prvih 20

---
 lib/simplegit.rb |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
   end

   def log(treeish = 'master')
-    command("git log #{treeish}")
+    command("git log -n 20 #{treeish}")
   end

   def ls_tree(treeish = 'master')
--
2.1.0

Lahko tudi uredite te datoteke popravka, da dodate več informacij za seznam e-pošte, za katero ne želite, da se prikaže v sporočilu pošiljanja. Če dodate tekst med vrstico --- in začetek popravka (vrstica diff --git), potem ga razvijalci lahko preberejo; vendar uporaba popravka ga izključuje.

Da to pošljete po e-pošti na e-poštni seznam, lahko ali prilepite datoteko v vaš e-poštni program ali pošljete preko programa ukazne vrstice. Prilepljenje teksta pogostokrat povzroča težave oblikovanja, posebej s “pametnejšimi” klienti, ki ne ohranjajo novih vrstic in ostalih praznih znakov ustrezno. Na srečo, Git ponuja orodje, da vam ustrezno pomaga poslati oblikovane popravke preko IMAP, ki so lahko enostavnejši za vas. Prikazali bomo, kako poslati popravek preko Gmail-a, kar je e-poštni agent, ki ga najbolje poznamo; preberete lahko podrobna navodila za število poštnih programov na koncu zgoraj omenjene datoteke Documentation/SubmittingPatches v izvorni kodi Git.

Najprej morate nastaviti sekcijo imap v vašo datoteko ~/.gitconfig. Lahko nastavite vsako vrednost ločeno s serijo ukazov git config ali jih lahko dodate ročno, vendar na koncu vaše nastavitvene datoteke bi moralo izgledati nekaj takega:

[imap]
  folder = "[Gmail]/Drafts"
  host = imaps://imap.gmail.com
  user = user@gmail.com
  pass = p4ssw0rd
  port = 993
  sslverify = false

Če vaš strežnik IAMP ne uporablja SSL, zadnji dve vrstici verjetno nista potrebni in vrednost gostitelja bo imap:// namesto imaps://. Ko je to nastavljeno, lahko uporabite git send-email, da dodate serije popravkov v mapo Drafts določenega strežnika IMAP:

$ cat *.patch |git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done

Na tej točki, bi morali imeti dostop do vaše mape osnutkov (Drafts), lahko spremenite polje To za seznam e-pošte, na katerega pošiljate popravek, opcijsko CC za vzdrževalca ali osebo odgovorno za to sekcijo in lahko pošiljate.

Lahko tudi pošljete popravek preko strežnika SMTP. Kot prej, lahko nastavitev vsako vrednost ločeno s serijo ukazov git config, ali pa jih lahko dodate ročno v sekciji sendemail v vaši datoteki ~/.gitconfig.

[sendemail]
  smtpencryption = tls
  smtpserver = smtp.gmail.com
  smtpuser = user@gmail.com
  smtpserverport = 587

Kot je to narejeno, lahko uporabite git send-email, da pošljete vaše popravke:

$ git send-email *.patch
0001-added-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y

Nato Git izpljune kopijo informacij dnevnika, kar izgleda nekako takole za vsak popravek, ki ga pošiljate:

(mbox) Adding cc: Jessica Smith <jessica@example.com> from
  \line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] added limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>

Result: OK

Povzetek

Ta sekcija je pokrila število pogostih potekov dela za ukvarjanje z mnogimi zelo različnimi tipi projektov Git, na katere boste verjetno naleteli in predstavila nekaj novih orogij, da vam pomagajo pri tem procesu. Naslednje boste videli, kako delati obratno: vzdrževanje projekta Git. Naučili se boste o dobrohotnem diktatorju ali integracijskem upravitelju.