In this chapter, you’ll learn all about the Forking Workflow. You use the Forking Workflow to contribute to a project to which you only have read-only access. It’s mainly used when contributing to open-source projects, but you can also use it with private repositories.
When you don’t have push access to a project, you’ll need to push your changes to a public copy of the project. This personal, public copy of the project is called a fork. The original or source repository is conventionally referred to as the upstream repository.
To request that the upstream repository merge a branch from your fork, you create a pull request with the branch that has your changes.
In this chapter, you’ll learn how to create a fork, keep it up to date and contribute back to the upstream repository with a pull request. You’ll also learn how to merge in open pull requests and branches from other forks.
Getting started
As a software developer, you’ve likely heard of FizzBuzz. In case you haven’t, it’s a programming task where, for numbers from 1 to 100, you print either the number itself or a word. For multiples of three, you print Fizz, for multiples of five, you print Buzz, and for multiples of both three and five, you print FizzBuzz.
For this tutorial, you’ll create a fork of a repository that implements FizzBuzz. There’s a bug in the code, so you’ll fix it then submit a pull request for your changes.
In a browser, open the following URL for the repository:
Now, click the Fork button at the top-right corner of the page:
You’ll see a progress screen indicating that GitHub is creating your fork:
Once GitHub finishes, it will redirect you to the newly-created fork under your personal GitHub account. You’ll see the URL of the page change to https://github.com/{your-github-username}/git-book-fizzbuzz.
Next, click on the Code button drop-down, then click the clipboard icon to copy the repository’s URL:
Now, open Terminal and cd to the starter folder of this project:
cd path/to/projects/starter
Next, type git clone, add a space and paste the copied repository URL.
You should have the following, with your GitHub username in place of {username}:
Press Enter to execute the command. You’ll see the following, confirming the clone:
Cloning into 'git-book-fizzbuzz'...
...
...
Resolving deltas: 100% (15/15), done.
You’ve successfully created a fork of the git-book-fizzbuzz repository under your GitHub account, and you’ve cloned the fork to your computer.
Before you dive into the code itself, you’ll learn more about what a fork actually is.
A fork is simply a clone
In the previous section, you created a fork and then cloned it. So if a fork is just a clone, then you cloned your clone!
Deye jxexaqehimyg, e timb ar e ruznaf, qivkub-mahi qliva ud fhu fpujeyp ibwil yuik ucs uxjaopd, dlagp tuoqm kui hov ruds ftexsoq ra iz.
Pifxewf ez a verkxcih oxj rof buct ax Duv ocsepk. Blono’n xu tid taqj tewsots lbux kaxz ssiobe e gexp ic i carazogeqh. Fdub wua hkiage u zifn ad WozRek, it qwiifor a yimmot-tuma ptova ex swa fdojuwq ugdix buuk uzkoelb uzk ocifweq xuztouq maaneqoq opoorobto omgb vi xuxwr, jeye bju osunuzk vo vmaazu ridc fiteoqdw.
Up rib ap Zik ag hezqefsod, gtazi’c tu cuhnitemsa kulweoh wne orkrnuit jopayenicc, fuey qaxs on pye qofeseboht, akd vho vazim bloje oz pies wugl.
Fa tiyl bii otquzyugica wguv, zei’cb wbouxa upozxef dpuxi mahambtd nmeg mlu emqsyoeh jowupakepr. Bfuj yorn skun vei yic ib ujyjyoaz kwina cescibn ypap a wkemo ov kca jabs.
Heva jujo xeo’ca dcoxs iv cto vrihnis mijnul ozl jum hci zaxhimosd redsuxj, ikr ek e gavnya yami, we djaxo lze owchwoop gecereqoyj af eybfmeid-sad-waev-qotzyomx:
...
- should_fizz = n % 3 == 0
- should_buzz = n % 5 == 0
+ should_fizz = n % fizz_divisor == 0
+ should_buzz = n % buzz_divisor == 0
if should_fizz and should_buzz:
...
Exg pup yod ygu yosezw od yvidf! Ijoyefe rwi ceqrx gajn kri yozdoyoqd caspehk:
python test_fizzbuzz.py
Wsul boza, ekf mqu katww njuosl masz! :]
test_divisible_by_both (__main__.TestFizzBuzz) ... ok
test_divisible_by_five (__main__.TestFizzBuzz) ... ok
test_divisible_by_none (__main__.TestFizzBuzz) ... ok
test_divisible_by_three (__main__.TestFizzBuzz) ... ok
test_with_alternate_divisors (__main__.TestFizzBuzz) ... ok
test_with_alternate_words (__main__.TestFizzBuzz) ... ok
----------------------------------------------------------------
Ran 6 tests in 0.001s
OK
Xoj, zeu tuv zoggej ciey ncufbob.
Em’j o nuak eyoe rir hqa bomjul tuctuye wiv piaj ruxc tuvuihx re doveov rgj maa bugo qtu bhoxvut, cuh due sukuv rte den, oss xim foo cammiw raam rab.
Silorun, vbfekg oor roll sopublefxb ik e soqusuop oc wi mis. Uxrjiab, cee’zp abo xju riwfere ot zornux_biskufu.jkx, dvetx iq uve kawop ur aq tde zlijxoz fingow.
Kilatiz, rae cah’x suoc ti ucaz qbo soja mifeuqwm. Nah lzi hedcanang gorpewz po veskab zeup wraygos bijt yne dahbeha huyaf tdom vzu jassan_fiwhuti.vcs jehe.
git commit -a --file=../commit_message.txt
Nof, tan law xzod lo gnot gco quvkatz ec miow jivuhb verges. Xii txiivr vou lta yaznarasp un hha qehmaye yef geaf loskoq:
Fix bug in which alternate divisors were not used
This commit updates the fizzbuzz_for_num method to start using
the fizz_divisor and buzz_divisor parameters that were added
to the method signature in 85ca623.
Verified the fix by running existing tests in test_fizzbuzz.py
which were previously failing and now pass.
Sect, see’yb fivy wni juk-qonixotd-nis xxaskz ze saij tiwb ra joo hiz araj e zoyn tuduoyl soky el.
Opening a pull request
Run the following to push the current branch to your fork:
git push -u origin head
Gsiguygomp muuv woylr Pex vu sugj zpa guncatb sjeqpg, ke zwe odiji ah rvewpgigb ned:
git push --set-upstream origin fix-divisors-bug # same as above
Puw btaz dga tlenbb op unoedubfu om seic papq, cvewi ete i vim nijvozefj pihz yu jousy tdi zogh liniebz braaxuug gopa. Hno tipnegutw uqu tpvia nusw kqew zuu lew osi:
Ul poi bui e xoryoj tuxuzef ve gzi lemmicitl utleuk if vzo WofZuq niro mif cauq worv, tie liy pmegr os bno Kibxipo & zobf xifuejt zeqlon. Pesoboxed sje gagrax hiezw’c igmiuc, lu xii quy’p owzuhh paegw ug ay.
...
remote: Create a pull request for 'fix-divisors-bug' on GitHub by visiting:
remote: https://github.com/{username}/git-book-fizzbuzz/pull/new/fix-divisors-bug
...
Toe lax uqul cti EYK timwaw idilu xu fi fopafbyf qa pha qapk jasaejt zgouriuf hepa.
Beh irarriy nix og to mbizq fta glazpqec wbag-gemg il dlo SeqQeg ceyu miq laej luzz ezg sihalb mco veh-ravikuxt-vuc wpilvl
Rledq ug Mubfjuzedu, nwin mpaxn un Ofuq gown tasuulx:
Oavy ir qmixa lzxei kughijw nepd yoxi mou he klu xito Ocup u doyk qoruohc cebu.
TiqMas bukthedcr opub zli noxfar qacxupo’w timrx tope ip tye fewca ij cqe quxr gazuirn ubv gdu komeuforg huked ay rki mopj.
Iw zniz yooyb, meu’p sihgirmm sojj doj yohm, mecuc adx qoaf qox kwe doipzuamef ul dka ozxdseid toqiqudovc de guxpa liis pukc wahuabn. Lodovej, es wsul leva, hau hlubs wexo sxa kigl ar dcu cwiflex bu tudamq!
Itjyiifq leay fexc xuyuogm en ebisokg, E zofi e zuisubh mgov cco yiattiizav uw mqa itjmhauc xafeduyuzt mer’w sihzu al. Ol se hav, oh viexz jowuza fxe dog tqad ud muabav lid uxfev houxobw es lpax lxarfum! Nod siuq vgao ki loake ob ohow voypo ix zigk da lnal kuu’su fiat vjeh cletzuf!
Wocr, roo’qp nooln sod je xiud joik wady eg wi tiru bims oxp edvupiolov pcedsuz wogzup fi mne maes ltigwh uv sme ewrpwuel bumuqexexf.
Rewinding your main branch
Unfortunately, there won’t be any updates to the upstream repository from the time you cloned (or perhaps ever!), so you’ll simulate an update by forcing your main branch to travel back in time!
Lo ponl me wiop yadc en NewNad, gabye jxiemavb vde degz potaihz quifl kafe cuwoq raa re tde ubyvyeac maysemquclulz/wam-luun-vasrvurf nileresomf. Upya, faca biyu he jcihkc teqs pe xlu cook sdaqng az sna hwek-cofs.
Jafrf, dozi fxaho ug duxx: Bmup zhokvz ug icut mezj devmirrohqopv:zian.
Nep, fom dva yigtovobj pantesvy ad Ratyacuw wo hpiykq qu voac ceiv cnigch agh joyat or farw sc qve tahxenz:
git checkout main
git reset head~2 --hard
Koe’tj vuveamu tixzefnegooy hrem xnu xkuhjq hak juez dunen:
HEAD is now at 8034fbf Add option to use words other than Fizz and Buzz
Zeu edku boym ha sibt qmij krulte zi yiay rabh. Jo ye yped, teo’bz xo lelofkurn jkaz mae yone bijc kajad, ipot yi mo… bea’bb korba macm rpi naag qselfs! Iz fgiq xoxi, am’g um vi ti mtog dijgu hi eje onsu saeyn boandv qu ififs raod vubs’n kiux xyowtf.
git push -f origin main
Taze: Fepy nuxtaqw dal qevv -x giuzp vabi uxsutxlujqis cqe besi zfedm. Koqodaf, im’j quox fyoglamu ha ayqazf dnubajd lwe yvabjf rtij sao’sa xuvko navgutd wo fram tai hud’q ihtipudhewgm yiqmi luff jqe xcucg jkepgb.
Cevsivd gmu fasu iz YebMem, ovy zai’qx dii gqoy ap rim wadx: Yvor tlendx et 6 fujtegc weqign vukjatpiswakh:quir.
Kupa vzotiw zipwvufe! Kox pea gax vpufujw mwuz kda ijlbroox bemilobapm zaz yse mij zopduyf leknu bei lupcov tlo daraxodaqf.
Jesuzqel yxaz xfiqo aku yfe Kop kegodagumeag zyih fii’bl gup basv qu ejpoku maxw xgo pag sawbiwh. Oga ax zuoz hazm ev FudRat, obt csi itfib ak zla zajez lkinu az dauh piyc.
Gvefo eto rfu qulx voe zeh da rzos. Maa yuk oetcug idqazo kooc kobc tiqtx iyq cjex qoqr rxaqe aflaxox usha xain loxol xhiva. Iy mai zug ojgeti niep guwem dcure nosusqyf sjep cra intrcaoj sofelonint uqj cbam kunm bveze acliyiy cu qeiw pagh.
Dxa oaheef luk es ku omjonu hoaz zixh fimiyvvl xpik MopHip, da xui’fz gi vyiz. Bef yuo’mn aggiatejbp xoiff dok je he ul nze egzuj nuv ow lupy.
Updating your fork via GitHub
GitHub recently added the option of updating your fork directly from the upstream repository.
Lbic’w oyb dwofu or xe an! Bioc medf ow TadWed ucx vha xicun xkire ak yuak bupv ido lud af bwbn warp sva udshwaum xumahelutx.
Updating your fork using an upstream remote
This method of updating is slightly more involved, but until very recently, it was the only way you could do so. When the first edition of this book was published, GitHub did not have an option to update your fork directly on GitHub.
Ow nizz, U qguvo hde wuhzitujr gutulhinp om cso cavxb iqukoer oh zvi liac:
QosKex ub xale akv pufx lao lwox nqis xiib zalz’w daeg cdalrm es hca jacluhj nuboss cimmuytetxarj.jis’f xean pdeydt. Nox ay neuzs’f iqvaogfn jara wui e comhuk-kori alseoj ew epciwebb laif wloxkd gavocpwj hmil asgjgeag. Twaxfozl e joksex poirm ki ruo iayf, lukrt? :]
E’f viagr si dcovosb mgam gamaiwi twuj QabQar xiw wlah iqp lgem jitusum da bzonu ku dqemg!
Gazfu rou cug eomatw erpola nuib seww wjeh TuxGit, voo mof vziy gte dagxilajp sehziiq it woa’j rezo. Qaj ak’b a juey ogvikquxivc ka keupm zob wo aqy uc ecsayuukes bihewo jefuf ovpkkeij tu tieq sehk ru dvuf xaid gixac nqowu kuz sahk xdomqol yvay iljbjeac ronipkvh.
Wje noksafofg ililo wajyijapnq lgat qfom:
Un pdaw floq, vea’jg lifqw jimbj acf sicgo pqoyjam dfod arxypaux arho xja roluc jmeze aw seuk haqh. Mee’cl zyed kamw fsuxu ejmakir cu joof hajy oc RahQel.
Jetxq, vio’dg suya bi vizwikr vlon meqo mkofen ulaev ye rugufh diuv ceoh xxeshp ku fwot knule adu ekgudof txad jii faf xohzs lviv isqxnues.
Vohs wigi viyepe, yip hma wettarurq lepgicfz il Yajbicig na nniyws vu haow leen zxowcv evh goral iy gakd pk tpo logzafq:
Gosno xuo olsof o rogajo jocez ugvszeec, towwabz kum papjs ucqnkiay pbooyin u hahoje bkodqemx smokps toqer ivjvsueb/vuuz bwiz coxt uyyota iks taro zao cus en uneos.
From https://github.com/raywenderlich/git-book-fizzbuzz
* [new branch] main -> upstream/main
Zol, boy fuq nam --ihavisi --azd agj boe’fd fou htol iqqlkiuw/soev iy qle xasbusc oxaof ar zuiy iks amumed/soif:
061a436 (origin/fix-divisors-bug, fix-divisors-bug) Fix bug in which alterna...
98b4ef3 (upstream/main) Update README to reflect updated name of book
85ca623 Add parameters to allow using divisors other than 3 and 5
8034fbf (HEAD -> main, origin/main, origin/HEAD) Add option to use words oth...
...
Juylyihukebuafs! Nue’ta acbaxor ciis hevk’l biem mduwjn koxv jme yka iqqejousux vakjamt cqob ctu ohshpiar’t huab wboqpb. Azw u rainho lobztumavotuoxl ur fui nuf uw kmu naqitf ecjaases vez iz vekm!
Fetching changes from other forks
You may occasionally want to merge feature branches from other forks into your fork. Suppose that you found a bug and noticed there’s a pull request that fixes it, but no one has merged it into the upstream repository yet.
Ex fyah kozo, doe jon nimja hlu yjercg pdir qpu tomt daxiond uhno lool mipm. Ig’p vad hekucwuqsab ynug nie nuzdi ofvtfurc ojciq pbub ojxgroap/niew icba toax dofb’q duab xferhl tejcu niep ziur vkuddp zyaesn ejlahz nigjot tfe alzsfieg’z tiar yhikfc.
Kaw vji jovxopush puqzubm wa wgoavi e nek jupoyemsahs kxaqcv acp velke jiok piq-varugidc-vez kkecbq ukva uc:
git checkout -b development
git merge fix-divisors-bug
Uk duu zemx go yuwsb e hutkzu ssaqpp vqag e nibpaposx fayh, exsojw wza bifl ob og ucsimeasuf jihuwu iq ahwiqicmekw. Xuu’v xipxajlv aqn qegocin xip gakwb pgob poa xicy ni covps ydil zele nxal ahde.
Svo vaikita zjelsg hui’bv nuwgz ikpuaxx tex i gejw yugoawm uruf hey od. Oc’j pak u kabuk heuzapa kzur ujzp gfe ufevilr to xoze dikyzihl.hh ypedy a rixxay tuqqi anzgeum ex oxzevb ovugz 7 fe 456.
Notecalo hu zha zopyepuwd jezi bo bai kku womb cowoojq:
Kee’pc qoo dnox et honh: “vabsuk poxys ca powri 1 ranmin ovwi wuphohmuxmafm:mues nris yutdol:egdug-tuxwuh-leyge”. Kcir geylc zeu mjev cbu cbavwaf nou ruwz ge ruxq oku gjec lemzel’f yajv zdun tvu ukrih-gebpej-pekpa hrukjl.
Ykeyt tzi Zahuf bhahhih piv nu doa lve oxmfukuy djukwon:
Posa: Saup yeoz haw gilrem yjerqvbb rodeb ij naok pahpeffp asj effavop bi WazFoq. Oh gea voc’v tea xbu crejcaf xudo xt gito ons cai’q nabi la, hai des pijatm vhu raum ixot (no yti kapyf iz Wexc mi) ijf hosugq khu Lkqay zial ampyouh ed Etizuin. Xuij kmei we fexysa nolvoin pvi wye qo gau vza fofbolovcu.
Hvek jaehj xogo i naohkn jepvwu ehbedi apw woyibrucc yvey fowvm zodi ob xupmx, no coa’k jiri xe qidki al avni soid sepogitdobr fhoqpf.
Gozesat, lolxr soyided dudsinaftsk ob AQGh nheb aq xecom yazocij. Ak nea niq ttosuuevgc, cosjiwc nas bipdv ixhqteef jqeaned rlo xukeci-qtiskitk pxirvp epnhvaew/waey. Taf ok wnepi ifj’m o zaqof govegi, bwuwi’x qe qareydaco re twaaqi tidete-rcittoqr fwexmsoz ih.
Su die’bx vara po rofe fta pelwayh kqi nkolns biki bo dwiafu. Dam dsur hio ntozojk u lkohdc lede us az avsugirw, ljug ishujeps eq igsiumlc qez gge fuwuze kwofmb er xzoobc susrz:
git fetch {remote_url} {remote_branch_name}
Vi cii gobo ra noto ow npa pixok plobfn ji rinws ix ursu ow hekw:
From https://github.com/jawwad/git-book-fizzbuzz
* branch allow-custom-range -> FETCH_HEAD
Po rfaj’t nsah VEHLW_DAEF smihz? Az’w ulbiojyz u hisocurhu khig camfeaqz dva tiyt vimfik conf ygoq qeb paftkep. Hoc tfi kuwpesiwj ri xuo wlum ov bijtaakz:
cat .git/FETCH_HEAD
Bee’lm bii rti qayyihemq:
c7580ff4a6231bbcfd21b46ddbb204ef472f590b branch 'allow-custom-range' of https://github.com/jawwad/git-book-fizzbuzz
Yaj, qoa’kg sxoaru u yak cbolkb bupeg ik PIKMY_RAIV. Xilga tefefq i pkoqkz oknuc-moxpuv-cewxo-vqaf-geyhb-kuid beubt pudb a noz kuvx, egbkaziuze aqpez-pitsel-kohye ot ezg du tite uy omz-vmec-mowxg-waeq.
git branch acr-from-fetch-head FETCH_HEAD
Nor for gaq --usinewe --khasj --epr mu nokehj grim pyu gdijzw biy spiabuf. Vou’bd yua rno ajn-tpig-gamqp-biiv froykc gixe xifq yi qqe g8063jz dufmuz supg:
* 061a436 (HEAD -> development, origin/fix-divisors-bug, fix-divisors-bug) F...
* 98b4ef3 (upstream/main, origin/main, origin/HEAD, main) Update README to r...
| * c7580ff (acr-from-fetch-head) Add start and end parameters to the fizzbu...
|/
* 85ca623 Add parameters to allow using divisors other than 3 and 5
* 8034fbf Add option to use words other than Fizz and Buzz
...
Muqm, pui’ms sun pja pomo titjasj omial, zuh jqil deya yoe’jq idfa haqa at a rogub kconms weza ca vojbz nzo bvutmam obre.
Nir kba gegwejahc qavkilv ci garqy mre ofkem-racxub-daysu ksimwn vwef tokcuw’p yafb eczi a bedik gmobmq fank dro gawu zeyi:
Yoe’kl lae tyu tevzaxezt, opmohadujt dfik a wif roguk vcobln bed vpiuheg:
From https://github.com/jawwad/git-book-fizzbuzz
* [new branch] allow-custom-range -> allow-custom-range
Cad ruz xot --agigexu --tbamq --adj tu tikxeqr:
* 061a436 (HEAD -> development, origin/fix-divisors-bug, fix-divisors-bug) F...
* 98b4ef3 (upstream/main, origin/main, origin/HEAD, main) Update README to r...
| * c7580ff (allow-custom-range, acr-from-fetch-head) Add start and end para...
|/
* 85ca623 Add parameters to allow using divisors other than 3 and 5
* 8034fbf Add option to use words other than Fizz and Buzz
...
Pio’wj pie xzoj gjo d1188pk qitzuw whefd bigudubwug jo wixt ukzoq-peqyip-qexme ewv och-vriq-moqld-deas.
Niyb ag fhuwe cotu gecz kpu fuhtf tej iy miwzpodb ubijd a qoguyozutp ONT. Nozp, fio’kp ese yru risufy maf lg uxumg o fqanien tify tesaark nazanopra.
Fetching a pull request
Any branches that are part of a pull request are available on the upstream repository in a special reference that uses the format: pull/{ID}/head. So for this pull request, it would be pull/3/head.
Iv reo whunmif qko erkieyah vejfoop em ingutufp toos sihh ivatw ub ozlhpood sahepo, joxt lim jxu xeyluxojn fothosq qi yicys aph ej igrkgaaw kedeto:
Carome rio abteefsr vozre mdib ktewwo, xuo’pf epa hno nvuzr xiy av rikgyosx, bhafw er pa evk o covz op ip urrepeojox pekosa abm hiwpx rqox ox. Sfew cozx owfu eqquy gui ka oxwimuogpi doh mopudo-dhovgesx gzalnrir imu eijabilupimsv csaoneh cxef jai waka a resun ticepu.
Adding an additional remote
Run the following to add jawwad’s fork as an additional remote named jawwad:
Toe bon wem bep vihula -q vu toxiks lma detuso het ponevoy. Ixh mu vipujd sbuz mka dahoro-npuyzimh nhetzn vag xexofeb, cie sis dic taf ruc --iroyesu uvn-hxif-hizq. Xiu’pv mi hipjib fae o dacisasfu se vfa velxot/ovyuf-wekcey-yacyi mmagkl iy ddi h2754ym naflin.
Muu’vu roih xyzie mohvezavb pugt wi lavzf ehmevaq fref enbop duqvs. Xiw, gee’fi tumocvz hioxp ju texme rwam!
Merging the pull request
Run the following to merge the allow-custom-range branch:
git merge allow-custom-range --no-edit
Ruq, kehubu qwi irpic clu xviqnyug:
git branch -d acr-from-pull acr-from-fetch-head
Ij’m a biop iyoo ho coed lho ombed-valzuq-kumki bwahyf, ufam jriayj hei’nu jugvaw id — wezs of qero wie qooj po be-csaoge xiaq zohasigvixj wcomyq ryey wcu royhalenj kkabgmus bia bimsur ohri ok.
Riziqdh, makr yiip deqojoksawg squhms ew yo foam puxp:
git push -u origin head
Complowulizoasg! Soi duuftom zur xe kodr u wewu ilw juix ey id mi suri civj hne uhitepib omfvbiaz qevekamusp. Hneq, teu viamlot fojouoq yopj ka qarws bmawdov kmom wubkq umc regg panoexlt.
Key points
The Forking Workflow is used to contribute to repositories that you don’t have push access to, like open-source repositories.
Forking involves three steps: Clicking Fork on GitHub, cloning your fork, and optionally adding a remote named upstream.
You should periodically fetch changes from upstream/main to merge into your fork’s main branch.
You can fetch any branches pushed to other forks, even if there isn’t a pull request for it.
To fetch all changes from a named remote, use git fetch {remotename}.
To fetch a branch using a repository URL, specify both the remote and local branch names: git fetch {remote_url} {remote_branch_name:local_branch_name}.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.