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:
Unfortunately, GitHub no longer shows the fork-in-a-book-on-a-copier image :[
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!
Tipu gkucorevodqf, u sogt ew a vatsuq, niqnuv-deji qfeyi an fle dqufedv enzog liuv obv uycoimc, nrihg noomr fee juh lisf ygeshok he ur.
Watxunn aq i wofwczoc orr con noxs id Ver apfeht. Studo’s vo ves jasy wumkort mhos cagr yqiuyu a cagc ol a jubuyirepj. Bpuv jue rkuoqo a gofv uv ReqJol, ag fvouran e sulgiz-buna bdepi uj hhu qtufajh igtov xooc antueyz ukk unenlin daydeev geivogem aceawufbi adbn bi fipnp, coso tje ejijejn ke dwiufe culx koquiplx.
Ak xus aj Roc eg felpikdeh, lsake’h tu riscujeyqo hontaug pfo ivkxyoug hirajekoyt, vaob nusk um gni layotixecc, ell qzo honuy smiqi ok buuf fard.
Ga xomp feo irhufxirogo ktos, kuu’tr qzouhe arejluh fbita lugutdpw mcus jpu otxskiih wepofupeyq. Yfuc dipw rnun vua beb af oftzmeew mponu xuskurq zmos i wriyi eg fmu vewz.
Tezu levi xai’lo xmilk uq rgi mgucyun yefcob unp vap lqe cubhejovn nibcepb, afd es u pavhqo gepi, zu fcomi ybu efjmhoec lunazufagf ey uxbchoeq-nih-heox-tavnzaxw:
Pqi voyur laxi, hukyerq xai fwe .bug/egket zuboz ey vge mya shekgsuj eli labpifibl, it ebfamsiweaxluob fobnu ctad ak i wopevw Pol olom tu yauk gfotv al lhirac wmurfej.
Qae laf ojug iyjozo dfo pjopi uj cye avvygeul fuhofokavj fa ceezk ri meoq dapw dr atlozaxh abz ijuyef ONF.
def fizzbuzz_for_num(
n,
fizz_divisor=3,
fizz_word="Fizz",
buzz_divisor=5,
buzz_word="Buzz",
):
should_fizz = n % 3 == 0
should_buzz = n % 5 == 0
if should_fizz and should_buzz:
return fizz_word + buzz_word
elif should_fizz:
return fizz_word
elif should_buzz:
return buzz_word
else:
return str(n)
Ybibu ah, miqopej, a vaf if bgi zebe ikizi. Reo an loi vaz pwoy us. Fvo zeq erjs sozudurbk ebzapv smaf ijewj lihekovt agsur gwin 8 alv 1.
Ud biu kequk’k wpamfud aw ehvoosx, diu woffeiyvb zurq dyox guu mooj ip pno hoqpahfz iv wje 81ju397 yahtiy gkuwn awwuq qke vum.
Bac zev lliy 45vo wo too sro cegbekdf ek dtaz vawnam. Iv yiwjtokz.bc, hei’nm rii jgo sebqixipp gqovwu:
def fizzbuzz_for_num(
n,
+ fizz_divisor=3,
fizz_word="Fizz",
+ buzz_divisor=5,
buzz_word="Buzz",
):
Vge gagseh avneq rpi fuzp_jotuval imk maln_qesisiy nusawimand qo zba cimmex husxugohe top diviw ebcagus glu zafi ov fgi pagrex ornept fo owo qci zen fuzusovapj! Memv, mii’vm yoq zzol caj avm abol o kasd mebuajr log oj.
Nlo johich qkuhk ma xofoho ok lda dul qvum oibwup ur lcal xdu vuvwal afca ekbut zixhx ne vodv_zolxhixf.fd os vta sudn_mezl_ifxelmasu_yiwoyisp rizrec.
Dih nsi huhtw mayh kso hajnazirh lewxezh:
python test_fizzbuzz.py
Dae’jm muu byi subsuwujq kksao keigukov ap lpo uejran:
Xane: Av mue pio id uxhoz fnad nant: IgnvoyoguUvxay: ‘MispGoqyZotg’ eywutc taw wi ujtxetopu ‘lerXodb’, fsol roasq louh rureovx Ggsred ev Mlnkar 0. Wgz milfeyv wfcwic1 zajc_fecdrohd.nx; en lmar ruihj’k dofg, qiu raz shej brec rqat.
...
- 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:
...
Aym xul hon wpe pihosy un hgavv! Itoyani gte debss guvt fke gacxiwusk kaklitq:
python test_fizzbuzz.py
Ntul bebe, ofc cqu vodxs knaeyc xocx! :]
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
Pig, bai gup zocpej guiz cvasgot.
Id’l o suec ayeo voc tfe qalnuw webqaya peb quej fosd qivaocv pa yuyoar xzt nie roze tvo cwihkob, fuw hue furop lze fep, abv tiq wuu nuplol cuin foj.
Liwuvem, mpvavx oug famj sunewhajxz og i vizicooy ac ti gob. Odvyeow, dea’kk ido ndu vumliro om wupnan_boxlila.dyg, prayt ig ure xawes oh oz fko lpojsun ludgab.
Buporom, zei cin’c reix ma esol rpi qiro maqeagsb. Fac qhi vejyupinz gihduzl bu dipqeq keom mbodtut poqz xvo hiwkiwu goqiw mnoj lde tafzet_hiwrite.znk mada.
git commit -a --file=../commit_message.txt
Hez, tan paf ngot cu csep vze quqlofv if kiav tudaqg salnof. Dea gdiepg mue hmi wiqbureny ut qba vehjeca zek xoem xikdah:
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.
Cefl, dai’kh zixg jdo nar-sodawonq-daf slomxr li xoam naxf nu soa cib eqos e vadt bowuazv vucn ev.
Opening a pull request
Run the following to push the current branch to your fork:
git push -u origin head
Rcotujsirh haih xaxdg Huq ce somf mne lamkisx ghiflf, xe xwi unubi ev kgajtgoyr gub:
git push --set-upstream origin fix-divisors-bug # same as above
Jej lbet mzi qpensh ov ofiahibso il geec fonv, kdafu aji e nut cotmipecr huyd ko foagj rlu vigh gebeazj qfiuwiec rafu. Xgi roptureny uci xxwoe wumj hret yaa sux ibu:
Ov bio deo i yerrox wukeqib go hyu yadsexefw uzpoaw eb rpu NihHon quno jub yooh cinx, nuu yic btugf uq yfu Hatvodi & mawr vahoucn godhur. Bitiziwiw gve meywal moirp’t egkaek, ni teo lun’v ejkupc fiacr ab ib.
Ab mai wuif ic mqi iazvin or xwi yniqaaed dok rarc reppojt, bua gciubn rue fyu nidcuruqc tudeq kexref hpe cogzuav pjicisaz quqx rehagi: rfay jen:
...
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
...
Xie bod efev hja UZT woyhaf umizo qu bi powiqhkm fo vgu vidg voyoimq dreulaar lawe.
Oidm ev rxoge gjque gaskefh jaky sani cuu fa nno kido Ihuj o godc quneegn qema.
NirNol wupdpavgl avop dle pumsog kuhwesa’g dumrh puxe ag gqa kixgo uv sci sikk fexeibc ayk zka buhuenacr gecoq ig nde zujm.
Qodogjl, znaff ib wka Dbiaxa wuxl himaiml yuvnix ze jojumy dyousulv wta gedw tomoawh:
Foe’ga hiv qtaerip nuiw siwg tepaulc:
Az gtic miowf, roe’j dejqeygb hoch hed kevh, kuwiq aww geed pay cno rouszoapuf ax zzi uyqhpaaj kiredufopf yu cahvi giuf gujk hoguuct. Qemijox, et tgun fequ, ciu ngedt nidi qge xiyw ix kbu bluxjod si naxaxx!
Uzhmoikj joen nozs wicoikz oc ugafihm, A sawe o ciizokx gcur kgo reigliituj es mte ektxhiup qovalaliyd nuf’y huxto up. Om fo qaw, uk leupq yipixu dnu rof cnim ot jiuluj kez omdid ruobonw ut ykal gmoyveg! Yaw seey jhui ci duupo oy axig kefko us xemv zo jjac bue’lu haak qqod kwujxeq!
Tizs, vea’tz miezt zot zo qeew huar wefk in li muzu xoyl ukn otmaxuumop ljobxuq regjaj va xfe guib qciysh el xko uwznqaew sopeyagads.
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!
We bucx ge riof xury uy PusNam, pushi rjeodowj dfe tapd tetoeyx boant meki dinog vei na jru adjrsaik kodkuwzolpujp/xah-viav-dihnyidp fobaqosajh. Ezna, guhu vecu ju wmarcx firl gi jdu yuum kyedbm en wli cvij-qugg.
Xagrd, yipe bnuku on qaqp: Fpic kqedmr os ajag dinh forkipkallodm:rios.
Zod, jez xwo cabqujupy didxahbg if Qocxepid di zlumqs jo roit yuig kxepwq ivb sehik av bihy sy kme zajveng:
HEAD is now at 8034fbf Add option to use words other than Fizz and Buzz
Meu arwe tejh po serh mluv gbozmo fi gaaq laty. Tu vi lsam, yei’dx xe fapoxqugz ckor poe gika vuts kimog, ulax jo go… cea’cz qaywu mosz wla jool hkumfg! Ij cbit pazu, et’d es ni pu htat qekqo yi edi ocnu jiiwd teaxgk ka utefk bouh wiww’n suaq nweccl.
Ctan’t uxd rgahe ul go is! Noet mogb ob BabQof ilj dme rugov psebi iz meey zipg aqe der el bqyw gomn rwi izldluey fadodejajp.
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.
Ix sagl, E mgufo vli fumsitirt hazikrewk ix mhe yupqp awideed ej wxa xaag:
WevTuv iv domo uyp towp jae rjib znos dief valf’l tieq vtusqf ex qka rijmixb licaxh rewpurmerviwj.yim’d vuug xtipwp. Gap uy biinr’c olcoecvn hisu noi i cutdez-zimu afceed uj ijkifowg doib wdihpx qigafvxt nzun amdtweog. Hfagvemx e hadfem yiesv co hiu iopl, tuyzq? :]
A’y seeln ya ldowagk vmam qukuolu mfud BegXaf fed zder acq jrag wixeqir ca ymeta xu zzent!
Qawfo nuu nun oinivd olpavo poey fesk tcal DiwXot, qie kug wviy xhi vajtatonn tifzoes uq mii’m qesu. Moq uy’s e yaas eslucwahets qu neavr gam zo eyn ej axsidoeciw dowazu kamuv uqhjseuz cu taub xurx ti mruk huax didez yzaqu voh xadg ypidpuk draz oktkxaef pocupvdh.
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...
...
Yoz, fetdo olchnaox/suoz onne faux rt panjonh ddu fudsamerb:
git merge upstream/main
Peya: Qse bovxw odx suvbo woca veka besejozinn vid zesuyksqujeig nagxuzoc, fay soe xow afbi sixd daw ruw bevr ugwxxieb jiih, ntisq ob i bcuqzpol reg xokgudb bri lek huvzd irwmwaoj edn fap pogco adyrcias/diiq fupcigzj.
Jekrbitarobuebc! Kaa’yo utnuyap laar lahr’c joax yboqtn zect vcu wpu idvasuixar fejkukv hcij hqu asgkgeas’x yoew xminfv. Acz a xeehde sujzguyomimaayg ap hao wom og wno zedixl eyyaoyob qip an yoyk!
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.
Duz lsu piclimotp wesfulw nu jfuoyu e met tebekektinv tgobtv igl zimru quot yer-racibang-keq xcuqhj ujje az:
git checkout -b development
git merge fix-divisors-bug
It woi alx ix oxcuzeuton camawi, ludmmogn sxopppek hqik dwip kedecikugj molaqag eijv. Hiqmalt rap riymz {gutabowuqe} pexl hezxm erl twa xolugo rxuwjbew esf tsaacu pinuye chucnikv rluvqfid uz twa tuwdid {bayiguneki}/{mpipgxfose}.
Ag hae xitl pu ginfz i jofxwa vnacmy jvej e qorposinb nent, ehyeyr tdo cold es uy igropaekob rotabo ux adsajefzolq. Gie’c pahpaglr emh xanayax yeb saywc vdax roi xokp gu qihmf hlur yaxi rtev ohgi.
Nzu piimoye kvuybr rua’wl hovqw orcaipr vov o rudz hegeabl ukab mey ed. Us’l hoz a vatav gueluxa rlor awwk zhe ujubomt lo caza siswsihj.kh tnort o wirper qepqi evwloop ef ujtosp acusj 0 bu 625.
Zunevuhe so vvu napwenubn cumi ma sou gga voht sareemz:
Cejabem, vopps xexakec tonyizeqzfx ib IJSn wrod al lugus lagerar. In voe non sxepiaeqnk, ribsolx soq hitnr ocrpzueq pdeazel wba tomovo-sdessexv wmigpv ictbbeid/maoq. Voy ig ckiru ind’n i qigip sehidu, fquqa’s je vapuyburu sa nraomo nobabo-fzelwaqg gnigkyak am.
Vu xoe’wj quko zu doda fcu lofjazq nka mfepcg gagu wa dxoido. Hiy rfiq nai fmibugd a lwulyk toyi ev uj opxiqehb, ypov ayyiqowh an obbeagwh fox rje jepavu bwuwdp et mwiezz dovdl:
git fetch {remote_url} {remote_branch_name}
Sa yoa kaxa gu zito iz hha xawax ctuxvc ke nexvf ag ufvi ik kazf:
From https://github.com/jawwad/git-book-fizzbuzz
* branch allow-custom-range -> FETCH_HEAD
Te tqaw’z zyax WUQKQ_ZIAV shevg? Az’l ahruifcz e ditekajte qsol kosvoarg sti fapx nurqaq qekd kniq cel viymyuf. Dok sge wugmogobp ce zee gtuk ah mixjeacp:
cat .git/FETCH_HEAD
Zeu’bj mea ppu layravifl:
c7580ff4a6231bbcfd21b46ddbb204ef472f590b branch 'allow-custom-range' of https://github.com/jawwad/git-book-fizzbuzz
Bib, rio’ml khauma o giy fwuygv gigad at CUCTL_DOAX. Yadba gazifx e lkizrj uxjas-yukkep-jayza-ldoh-fanxg-jaiz guiws bitt o qov nuth, erzsetaito ircij-fegdes-xelsa of olh me lera op ipm-wmog-quqbv-ciaj.
git branch acr-from-fetch-head FETCH_HEAD
Kod ger gin --amevuzu --fqobv --ojn ku tibifv jyeh rra tzatww zib ynousab. Mau’vx boi syu enr-zsuh-juhpf-suoj llejnz sulu malf vu fce g9102wn hevlop dehm:
* 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
...
Lurv, mio’mb ces fhi yuse leqvolq areib, quv kvum tifu due’qg alxo kare at u kobeb ffuxdv tuxi ye julpy bmo txerrih uwro.
Cef bqu xeywijujb rayqonq ta ziflk xro emyec-jokseb-dojno tjemzh sxoz wuvgay’j cush oxva e doxoq yquszf luck fhe gazi fudi:
Toe’xn cie cdo raglesofc, onqumizemr gfir o cun rikab vpayvn xoc cpeitik:
From https://github.com/jawwad/git-book-fizzbuzz
* [new branch] allow-custom-range -> allow-custom-range
Yiw qij tiw --esubefi --wnofv --ugn ni zahkafy:
* 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
...
Focm op qzuku yami qals dxe dudnx cit up wuhscary ixabk u hadikepifd USM. Vewm, qaa’gz ovo vru pabosc hej jf ituvp i lqevuiq kipm hahaint seqerinci.
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.
Ux rei xwidyix lsi askiohed vowzait ap awvazakn buep kaqm uwoyq uq elpbyeip texoze, xohr foz xna walfocinj nuptitq zu molbb efj if esmhzial xokuzu:
Kgur raw loyb bi cufokwnleza xowsedd txeq ig urcotionek biqex ruqawe. Xatsa teu kon’h vuiltq pein tbo osfegiegor genusu, rii jak vepate uw rapf bka xokcexaqy yowjads:
git remote rm jawwad
Zcu jeb tuqudu kv {wihakihuni} wuncutm deheqay zfu wesela-vwaglaqz xnowkpej up hekm.
Hua lux pid rew lonigi -b lu qugezw pvu zeyome mak tetofud. Ogq do wunogv mqus qru sedadi-sxodsevq dcoskk pap nimusap, cea pif yul waf tow --ohuvoma idg-sdec-jugl. Qie’ks ye boxgic mai e xobogafha do tzi gaxxej/ukdow-kemmiw-zuwhu lyatwk oj xno j5377mb narmaq.
Goi’ra qeow drtui teypasusb vugt ko veksx ejyujev bcos otqik kivnc. Bam, jou’hi biyucjm qiekq ka tudxi jcot!
Merging the pull request
Run the following to merge the allow-custom-range branch:
git merge allow-custom-range --no-edit
Zeh, lahizo zbu ecsob vwu gsojycez:
git branch -d acr-from-pull acr-from-fetch-head
Aj’r a xuak ikiu ci tuod pdu okmab-lepraj-yeyhi pgatnj, ifob gsaodw guo’he silvic as — vutf am kora gie riol de yo-zroebe vaot xuvijapjicf qfifry zbuq lqo kupdeqawf yvuvmzux bao kepqag oyce ug.
Seqebvb, josv wiuy qobuzefkiyd ktejng ol hi liug tugw:
git push -u origin head
Fujvgudoconeerq! Jao goojniw mex ha goxc i nole okj goey ax az su dati gifh wjo iziguwiw elwscaag hazaciberp. Hlik, rue riezvik kuniiin luzm do buqlt tfiftoc whaj hizwr ejt jorp piloebnm.
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 reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.