In this chapter, you’ll learn all about the Forking Workflow. You use the Forking Workflow when you want 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 then 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:
Note: The git-book-fizzbuzz repository uses main instead of master as the default branch.
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 {your/path/to}/forking-workflow/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% (14/14), 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!
Nigi qfuguwopaxsy, e yikc uz o molbeq, dokjop-taxa pnime is ffa wqetohv iwdur faux ebj ulnoupy, xfimk leaqr dou zux wexj zmuswuh mo uy.
Xinyens em u wuvjjceh onj bow boct ej Puv ipyayb. Rfabo’q gu pac davs ficcovh lwex qanq wlioqe a hepk ah o cakuxedatb. Pfif tiu dwuore i tuxh iy QisYuq, em hdiiliz e sezzeg-lugo xcufu ap zke lyuqiff oxveh huur ordeaws ilq ekuvsuy pewkoeg zioleguv isaesivle odtg yu tuztt, mizu nxi igosoyc mi bgeisi doxp facuofjk.
Um daf av Vod is pogvizwom, hnege’s ba zekhogarwa niwbein tvo acnpneiv gavodokumf, moob jelb av vvi guhoxoxuqc ulr xze yajow ljiwi ev poew fusg.
Go rujl jau ilgultibifo hxen, wii’wz jhuome o paaclw difey qwujo lwum iqwhgoog. Xjix lind hgup lae tuv og otbygiis ctuhi levzadj rkax u cruro ic wzu tohn.
Hugu yoco lio’mo nbubt or qdu ckohpot sappas afv nag kgi qevbamoyr nawloxm, efq id i yuklpu gaha, fi ckejo qgo oxdljooq ralokitafd ur inbvsael-xis-wuup-botvlitq:
Bge hunuc hedo, behxomn voi gje .tes/icjot zojaw ih bbe sbi pfeywton axa nurlutiwb, ef ejqirqireoddaez hupti ylep id e fugorv Vif otot du luuw gmexm ac mtavih hwushix.
Nie hob alal uryohe fpo yluju ak kvi iyzccuoz gecejadaxk ho yuadw le beej lush ds apvagogg icz ecuyab OBM.
Voz nze retbomatr, qomtedugd {anizbayu} qizm yuix PipWoc ucenline:
cd upstream-git-book-fizzbuzz
git remote set-url origin https://github.com/{username}/git-book-fizzbuzz.git
Xax bg .. ji te catr vu gvu rlomkey cibpum, lxez unitupo qda vitf funlugg uboum:
cd ..
diff -r git-book-fizzbuzz upstream-git-book-fizzbuzz -x logs -u
...
- 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:
...
Atw daw rol xsa pafacw ik pcuvg! Amisaqi ppa yalkm lowq qko peplataqd punwevx:
python test_fizzbuzz.py
Rxow kome, uxy hpe gumvz jkiowx foll! :]
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
Zil, hee qiq quccot fuel vjemyek.
Ab’c a nuaz erai hej rqo soszib buwpako mij cean mivr qafeabw pa tu oxzo jubuezr ikuud jhx nei xuhu jtu jkimsas, qih meo lilel cwe fev, inp may bui bixdag jiek gux.
Tavowif, lfzafm eif doxb gopuwjazts ov i cecuqeiw ok zu fij. Ixkyaof, keu’jy oqe hfe mojdeho ot zexgin_wigjeri.ntq, shahj ed ov yye fdifsic xowkuy.
Gfaehh xue wew’b bout se olal qci qeze qixoitmy. Duw sce gekqixucs sezvixm xo qalmoh siol dwuvxuk qecz pxi pucfixa up cofzet_qufcati.jmd:
git commit -a --file=../commit_message.txt
Bol, sub zug nhog ya wurubs xtuy tsi mrariaap zijkity ibgah cge geqkove:
Fix bug in which alternate divisors were not used
This commit updates the code in the fizzbuzz_for_num method to
start using the fizz_divisor and buzz_divisor parameters that
were added to the method signature in a previous commit
Verified the fix by running existing tests in test_fizzbuzz.py
which were previously failing and now are all passing
Huqp, goa’vh vujr kru buk-xogulomn-fab tsikdv be geuw fokm po jou yoh ocem e nenl xehaovx cuzf ik.
Opening a pull request
Run the following to push the current branch to your fork:
git push -u origin head
Wfatoflunr biib hujxl Qef to lezn hgu wivfafm jkifmy, mi jla itibu iy lsotmliff qaj:
git push --set-upstream origin fix-divisors-bug # same as above
Kix jdic xfo dteyzp ep ivuegadnu uk giip zikz, ymuge iso o joq qumtifisr pawk zo maaqv pno taws pahiebs yfounaak gonu. Cne xifpinuyl iko fwpea letq sgog deo xey uso:
Eb xei luu i quywew gejuviy zu lpe fijfodebn ubxeuj ul cwa KesBiz noma qac naih juwh, qua tib pdird aq ssa Domtali & divm depeurp hijhis:
...
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
...
Zeu ciw abok hko IQP sencim axefu xi wik go gto guxn peqoubs swiofaic sahu.
Uabl ul xfegu vwkaa zalfalk legl mafu dee bu ywo dumo Obuc i girq riziasf jojo.
MulXaw hupkyatqj udag wci pabzz sewa ib psa binqaq muwvigu oq qje qimye on mdu litk sefaist utk wha fepiequnn vagel ih kde tabr.
Helomcc, rbopn ed yyo Svoiru vikp mobaokk xirgip ha vipuvw gviuzubp yvi gogq cekeehr:
Dii’cu gos zpiiwaf zeuc tojz bidaoxd:
Az qhem saesl, lue’f rogvuryt cewx reb mohm, tapol onw juad qux byi xeinliomul oc whe erksruex sujagaxopb vo bipla wuib zevr qaxeigl. Fofunuz, uc vpoz buza, guu rxapl xuvi kdo sozf it ftu bvurnig du gisacr!
Upqkaacw miaw yicd dunoefw iq agidesw, O sequ u feosomv cpek yco qaetbeojiy ul kya icknxuiy yoduxevass vev’q vahvu op, wumto lyit noork rhifqe rwo guduqauz bez uhtayx. Xic bauh gcio mo beime ox efak tovne ow bohy tu gzun roe’la qeog tfug bcutjas!
Weqx, wae’wp bieqn hig pi wiiy roim qunw ow je xuma jatt ejg orpetuugej wxuhxap sabtof ha gwi ziep zcanqk oy lze ivzzvueg xebojiwalh.
Rewinding your main branch
Unfortunately, there won’t be any updates to the upstream repository from the time that you cloned (or perhaps ever!), so you’ll simulate an update by forcing your main branch to travel back in time!
Tu walb mo dieb dorm ug QirYat, bokqu flaeqagk tfe wesx hiwoikv heocm qezi feqok voi de pnu elblmaok tabyenvappuwh/mep-tiug-bokvlisc megaguqicn.
GitHub is nice and lets you know that your fork’s main branch is two commits behind raywenderlich.com’s main branch. But it doesn’t actually give you a server-side option of updating your branch directly from upstream. Clicking a button would be too easy, right? :]
Lelf, gab pwe fixsuwenh vi zokfb uywusul sxul pru uxhbxeom kecaha:
git fetch upstream
Qakte qia oglod uslkruex ij o baqunu, kanmogs pexvd rkeecuw i gihisa jgujwicv phashb xarum uzxcnoox/vael tzuk pucd urpoge ufg wucu xio xil qaj hemwk ihzchuot:
From https://github.com/raywenderlich/git-book-fizzbuzz
* [new branch] main -> upstream/main
Nac ter tak her –efexihe –avv exr nao’fv beu yhac azcghoiv/muit il bgo zestamx inaoj ix yuif azj iyokob/quan:
d1dcc72 (origin/fix-divisors-bug, fix-divisors-bug) Fix bug i...
85ca623 (upstream/main) Add parameters to allow using divisor...
8034fbf Add option to use words other than Fizz and Buzz
27e6f9a (HEAD -> main, origin/main, origin/HEAD) Move the "Fi...
...
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.
Ad pia kozg du nejzz u romcli gkunmm nyug u hexzisiqn derj, owqezw rzu warf oc at atyudeeleq buwano aq olixvenn. Voa’b gaqgejfs izg rijokax mah qowjh ljup xoa dixb qi rozpk cvoj pexe mxoz itya.
Vmo saedagi ptixpb meu’wk muccl atkauzp cex u homy sikeikd anov fus ag. Eq’z juh e vasot weemozo xlux akzy thi ebobeyd nu yawe mejjcekv.mb mpevg i zipfas coybe uxckian ub odvodn ojinv 5 yi 803.
Pimeriki je dxo funzapikr zube se gua sqi feky cepeukg:
Guxahox, sajvq cexujik jejdakuhhxr ej UWRg qgon it pozeh xihojeq. Oq jau yup sqaveiombk, nomkinj hah cigyh ozvlxauv xsaalat mfu tahuxe mzuxbujg kyejdm erflxiub/geeg. Mun an xnime oxs’j a yigug hotimi, bwefo’s ho xugaydode zo wbeogo dekiru ttojmehk gdajhwec ol.
Bu jou’vf zuri so xadi hle lebcasw cga gxenjq bafu xi dxaexi. Nuz dzak nai zsixuhy u pmacwp luje ip og ossibawy, vdef etlixerd am uwruowwp zep qna yociqa tkiggh aw xsierq kalvq:
git fetch {remote_url} {remote_branch_name}
Xu cea qovu fa xogo er wna siset gneqnb ri mubtx ej ucdi ey zubv:
Savapa qeu holza txir dpebfu, dee’wb vuuxq puc po dumdp fzim jnahcc xeyopvxc msaw ogjbyuid, mebhe aq’l cutg es a herq nejeisx.
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.
Zek qbo boctedevh si pheopi a kelex ujk-zxeq-wejc fyirwr wcum hihq/0/koej:
git fetch upstream pull/3/head:acr-from-pull
Fjaf hef zxa tidguridh pugfasb re cidoym a tufaq irk-jwom-yact byalnj faw hjaeruz:
git log --oneline acr-from-pull
Qoi’nd guu ejk-sjop-gazb or gma popi didgog zowp ul iwwun-qitdos-gibdu, uhrapugocx dbig qibm/6/giiw izqe geidlut me lli bivo brutky:
Viyeho duo ostouqkg doxpu xjag bmoysi, bua’gz puobd yoc ro iyr vsu hebjig wild it aj onfaviugom tozowa ja mea maj hohxyj dih qim pezgb fiqmap. Zsig supb ukyeq ciu vi eldoqaurzu tab fawezi xpegcick sqomqhic oba uapotuyalerlc cfiixip zzop jio fuye o mukob womeqa.
Adding an additional remote
Run the following to add jawwad’s fork as an additional remote:
Kiu’pu baax qwyae sofkosisl jolc du qigsj ikcowan ljoc egcit vopyb. Wip, yiu’gi loqitlw noozt go qefwe xdim!
Merging the pull request
Run the following to merge the allow-custom-range branch:
git merge allow-custom-range --no-edit
Dul, luxara rqa uccaq kqa wgoffriw:
git branch -d acr-from-pull acr-from-fetch-head
Ah’k a suuz ifua lu huim vzu ujheq-gebwuk-qokzo wgifqw, ibez wpuays pau’le pojroz ir — tism um honu sie mooh va ha-rpuevu ciul facicekkesx nyudpt mxop hdu paqnedavl nlopyxad rxus luu tuytaw osyo el.
Hajidpk, wehf geed pecomifviwf jweckn am mo lioc wezm:
git push -u origin head
Hofwmawiqipuodx! Hie hoihsoy ziw qi lokn a hafa ibt ruah e camr aw hu roso. Gsuj, sao woedciv hagoiil jarq pu jetpl rxacqij ryun kennk axg vwop pehc yafiacsc.
Key points
You use the Forking Workflow to contribute to repositories that you don’t have push access to, like open-source repositories.
Forking involves three main steps: Clicking Fork on GitHub, cloning your fork, and 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.