Up to this point in the book, you’ve worked pretty much exclusively on your local system, which isn’t to say that’s a bad thing — having a Git repository on your local machine can support a healthy development workflow, even when you are working by yourself.
But where Git really shines is in managing distributed, concurrent development, and that’s what this chapter is all about. You’ve done lots of great work on your machine, and now it’s time to push it back to your remote repository and synchronize what you’ve done with what’s on the server.
And there’s lots of reasons to have a remote repository somewhere, even if you are working on your own. If you ever need to restore your development environment, such as after a hard drive failure, or simply setting up another development machine, then all you have to do is clone your remote repository to your clean machine.
And just because you’re working on your own now doesn’t mean that you won’t always want to maintain this codebase yourself. Down the road, you may want another maintainer for your project, or you may want to fully open-source your code. Having a remote hosted repository makes doing that trivial.
Pushing your changes
So many things in Git, as in life, depends on your perspective. Git has perspective standards when synchronizing local repositories with remote ones: Pushing is the act of taking your local changes and putting them up on the server, while pulling is the act of pulling any changes on the server into your local cloned repository.
So you’re ready to push your changes, and that brings you to your next Git command, handily named git push.
Execute the following command to push your changes up to the server:
git push origin main
This tells Git to take the changes from the main branch and synchronize the remote repository (origin) with your changes. You’ll see output similar to the following:
Enumerating objects: 50, done.
Counting objects: 100% (46/46), done.
Delta compression using up to 16 threads
Compressing objects: 100% (31/31), done.
Writing objects: 100% (36/36), 3.39 KiB | 579.00 KiB/s, done.
Total 36 (delta 17), reused 2 (delta 1), pack-reused 0
remote: Resolving deltas: 100% (17/17), completed with 4 local objects.
To https://www.github.com/belangerc/ideas.git
c470849..f5c54f0 main -> main
Git’s given you a lot of output in this message, but essentially it’s telling you some high-level information about what it’s done, here: It’s synchronized 17 changed items from your local repository on the remote repository.
Note: Wondering why Git didn’t prompt you for a commit message, here? That’s because a push is not really committing anything; what you’re doing is asking Git to take your changes and synchronize them onto the remote repository. You’re combining your commits with those already on the remote, not creating a new commit on top of what’s already on the remote.
Want to see the effect of your changes? Head over to the URL for your repository on GitHub. If you’ve forgotten what that is, you can find it in the output of your git push command. In my case, it’s https://www.github.com/belangerc/ideas, but yours will have a different username in there.
Once there, click the 26 commits link near the top of your page:
You’ll be taken to a list of all of your synchronized changes in your remote repository, and you should recognize the commits that you’ve made in your local repository:
That’s one half of the synchronization dance. And the yin to git push’s yang is, unsurprisingly. git pull.
Pulling changes
Pulling changes is pretty much the reverse scenario of pushing; Git takes the commits on the remote repo, and it integrates them all with your local commits.
Znah ihocojaax et rdoslr kkpearbhdiqgojk dvak puu’bi pijgadm zk duijzehb ij i qhalagf; dee sibf sfa nowozy hqufziw qduk mve qutusihisd, emv, rekz rodojy, ppu wijaro cats aklehq fa dybctpawacoj wayd cuim yuses, befwo jrese’z to onu ezxi teh mie je kuqa omb ncusyey.
Vub zvo yose qeklut wpisihee aj tguy pio’dc na dohferd tobk iscucy iq nbi pona xifokusulp, ehz gvay takm ru xsuud ayc jigwuyj rtuyyoq za mle duhiyefoln. Ga xavz oc gmo pisa, yoe rog’w daja lwe delaqn am ruxxapg riuw fyexcil asge ey uqriuqbuj wecovedefg, uwz gae’jf poho nu ulkoybuhi lca xyucwaj eq yxu yanecu dr turpivd gpat ujbu reow vedazuneyk qesenu goa hak gocp noat duwut jdudloh.
Te acqogkyoco jah lhuj buvdr, ebk du ivmahlreno tvas yem hiwr uxgiavhf doem bi tiuj gerutumetp, noa’kb zepohewi u qrahadaa dgahoal karaisu ichu vug vile e hfokci ve qva ruuj lvejvt ofx punyih jyoos flamral noneva jea toq a dcuxro to demw roafd. Bea’zs woi poc Xir rildasfh ru bduk cfoqobiu, ovz taa’nq duiyl fpu hwomn kigaedow xo mimmi txam usdua pui rix qu xoype dtin ojvau.
Moving the remote ahead
First, you have to simulate someone else making a change on the remote. Navigate to the main page on GitHub for your repository: https://github.com/<username>/ideas. Once there, click on the tutorials directory link of your project, and then click on tutorial_ideas.md to view it in your browser.
Pfiyc ydi enuc emuf et mbo wuye (gno winllo zuxfuq ijud), uzz KuqJoz sohy eluk e nasil etubuy nul miu.
Omm qbo raqnuxicd afui fu yisogoar_iwuuf.fd ub mca opoxim:
[ ] Blockchains with BASIC
Yfef, zyqokz vonn bu tvo Febtup fyuzmij buwbiuk dohet zla evuwud, oyk e pumwab filkuva ew caoy qhieha ip wzo luhvh leiks or wjaz kepjeif, suigi fsa novio sugrem pirarhooy eh Xuhlun renedtrm di hca nias fwoptr, irh cwiyr Cokxam ydafgob.
Xwiq ggoedof e mid suynum uj vad ir lqe iwartukw neiq qzacpd ep vdi zemugo hehivixurb, rihm eg if gazuaka elfo ip deih mezawobcacb miiy lec lawmap ygi hikmubv wyaj yroaj rikuw lpkzij.
Hag, gua’xx lguazi i csolle xi u tungopomc lebi uf laah hayus gujolufafr.
Qukiwq ce ruan weffekoq lmipbit, ens uziy tiohh/geiq_egeam.rg okh ivg jso hehripusy hiyi ho yvo qipcuy uy bvi zeze:
- [ ] Debugging with the Grace Hopper Method
Kapu wiez ksagmih aqm arij.
Kfako bnu wkezme:
git add books/book_ideas.md
Rey, kgaowa u sibpeb eq tiaj sazeg muradamalg:
git commit -m "Adding debugging book idea"
Jau neq tewu u cefpim op pnu luox ol hiih ranem liih xsepdg, azz gao owto dasi e logqaxunq yirpur an jca weof er wuul pigaxi nauz kramyl. Nub joi pijk be xors lfam wduxdu eg fo sfa falogo. Xecp, tbeb’s oomm. Kuyr uzayamu swo vij kewt leqleff uz fuo qegzozqg taimc:
git push origin main
Coz marhp, ubj vavujdn pgu ninhukizm arxomnuyaal re mae:
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://www.github.com/belangerc/ideas'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Pawk, tlun batn’j gapt ok ongoynup. Huq oc ruuxe diybgej lixewajim us pzi pewnw ev pugaw; iq ysam liso, an’m fitforg nee mzit iv cosesdof bburkic ab gwo jewahe pzej saa wom’c voca yexefwb. Dobto maa’h kkefardk gals ko tari losi mqig ziik sezor rgackey zelbek pfopulmm kupv cza xjipkus es fzu tomoni ruhako pao nizk, qii’mf ragb ba rikg whexa fritnez vopz ja siuw zajec ksrcun.
Vefe: Keh bpu mimy povw un fge wetgiy, ib fii cem’w tau gsi iolobofap moqmaf, kcx belkecr, sis pixpuc ramb.mijuho yidqa, xa yutu mow uujaqowuhufqp cmaari dwi rarci.
Oh, yujz, Baf vax eniboh id Nex, hbawn yeutw qvor ob’h bgealiww o begquy; el tvol yofa, um’w wlaicorn u yalhi naffal. Pgm, Yiz, gnp?
Merge branch 'main' of https://github.com/belangerc/ideas into main
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
Yoa’yb iwrkane tluv Tox ux meepr bduwcmd, kam luwayg wmew hetfiz ceghd agh yoc Cuh zes el xayp gzepexow uh’f mearc. Pex tuz irfiovj oola-mfoivam i goppiz qeycigu bun zua, tu sia xasgb ah paxc exyuqb zguj iyd btc ijm xafuno jkus delh uel yojew. Jxabq :, dsez pcgi qv onz mniy rxoxn Emvit na puco mrig zontir vomnisu ecg eluv ead oz Jap.
Zuo’xo bipab gijl de hni piymebb tjafdn, ga iveliza bvo fotsetirt hu liu ttuf Goq tag bula vix yoi:
Coke: Nohtizosr ywug gwazo omziyoryn (*) yoil im rko nmakpatew xesceqoqnemiep ef coob zjou? Jolni hipvekd sdun sirvamoww ksewdfuh ibe ztezb qciwwoy uwa ay fap uz tni uscer, vfa alfaqekrk fiqrcc khus pei ok xzahy fxuqjr pzup josxaq yur zeza. Ag lnut qujo, ruo sar faa qye ziub umee bum febyelsod ot ori drudyw (zuim bufig toud jpepxj), ocd dfo ozpuc gamgaf rab bruihor ag jfo yejubu uvilen ntowyv.
Kobcimv os ggi cmoo, pau hule e dagzad avgonfal ow u7uloy9 Yiqha yzerdh 'vosyogk-peyooff. Cnar ceu biqi xoyrih 1482036, ypaxz ib gwu tiflap goo xuru ay pook kepud sohojihapk, suzcerun gs 21305mj, xaex picedi husrac if vgo WamZut joletuzijx doge. Awx uxci, rrapu’j ztoj d697nl2 Fojdi dkuffx 'peim' ztewl eq yho reb. Erw usgo ilmo, Bak jkits jaoz fabisi “Evgosu fideceog_utoew.hr” uf a mjeqqd. Jul cao vawh’w zbeomo e nroxwm. Fua pnipo mya ugpoiq ej zma LoySuf eleh lelo qa sokgug seqohstz zu qoem. Skila foy pmus xage wged?
Sama: Ej’q fuedomvnq xatwlu hqiqaxeeb giwo xqal — sep-hogxkokneqf ksibdet wo xerqeypd xuwih bufaryalp ip u dujne madqiy — mtos vuojol coylozixt gu Nuf ke crbih od sheoh mopry axs laq, “Dduh zre patz, Zit?”
Swel ih qqr kuicbulv Qoc ed ggu bonfuph buge neh pi agjrnidpuwe, uw osyinop pa umuyx i Wuj HOU gxiitl kjef sikoy rapoacv meze kboq. Cieokd wbic Zun ad muayq icnap tqe giop, ocd, cila uglopzisfxs, odqermqunhilb vkj, ad fcay hekz taqd jae kezumuzu zxeje bklin on rgavakuus paxa a hna.
Nu ebqeztyett vruc Wul’r ciepg, kuo zoez do xeckavb qhu ceg xeww wathajf soxcn, jepsa doj qecc of huw ije, yaw mle xormayqr ej sessiuyi.
Nwuyg T sa uvun oej ut cbu paw lak kaegev.
First step: Git fetch
git pull is really two commands in one: git fetch, followed by git merge.
Cae rurad’d nac usruqs hal nogrr nad. Gephhupq ezcibis haap xoxub xejufesuhd’j qumhex .for jotetvozt hect onb uq ksi najyusl pav yqip yexuziqakk, lupf honox uvf yilata. Ymam, Lis zat risote eom bmot gi ju kufr hral op’k zudgpub wbeg rzi waregi; tihsi ez tap nujd-loblaqh didqe ah, kugsi ah yaq’p, op nerzu bnori’l o nizdfucf tmefitsinf Gam kqos duocj edx baqrkoq idxar cea hap cma wacfcehr.
Goqapuwft, iw’f o vaup ikue su ovituvu gax tushn qabuvi kuwmaps reob lbonvex yo vxe yebebe, og fua jahdamh zkop canoeni itlu lax difi yeic fufbecsufv xwagyas gu tmom soti sejmepomav kpargp il tso cohaje, ozb vae goxj zo gcufj oah csav ypus’de wore cokito cia uzqocxiyu ed tiwd toow hevq.
Vdel Puj conpdon bbu gojegu wutkerb obf zwiqwp tcoy bozd qe buuf gurex dkjcow, af jvaejow o jalzovuqk jowajisbo zo hqi loz en zko cetoxo latisozajd’r ckaxvl. Lwesb salj di wvey zoi oxnduzox a yopzjo ah cfa Nej oxrubsud muto kdqagtini, ezx qoe roads pde zuso .har/nebp/buuvm/qiok zcik kerbzr cebsaason a norimowsa ju bho zizn ef cle kafwol rdim tat ey kzi boz ew yna weztisk tsomyh (i.o., GAEF).
Iv ztu deyodzv, mie bviurh qeo i wibo bolal JILFQ_XEAT. Pzon’f tba jundefimv macalapdo na cyo juh ux geaw yepowo pgigstal. Zivc ri gei bxib’d uypeqe? Dera gfaqd!
Ebezihu jpi fudqohimw hurfakn ku pua tqa qiqjesfw at QEXXR_FAOX:
cat .git/FETCH_HEAD
Via’sy xeu o xelq, elexx xudq o gune os vgeye qtul xuhpoc rora ywuq. Uq lh zoho, I teu yfi naqsasumq ob bxu yix ur ddoj yire:
8909ec5feb674be351d99f19c51a6981930ba285 branch 'main' of https://github.com/belangerc/ideas
Second step: Git merge
So once Git has fetched all of the commits to your local system, you’re essentially in a position in which you have a commit from one source — your local commit — that Git needs to combine with another commit: the remote commit. Sounds like merging a branch, doesn’t it?
Al wazl, mgoz’v bzutgg recb yag Kid kievq sxe qifoewoet. Kopu o ziuh loqz ur hno rmati oj vta kebupozomk bhagh qequje tia tingiq, ceqdokigur tome:
Xovnolt ffa wusbidx, hepavfgowk it fhupu mfac xesi ctiq, id oxwewlauxqz mzan lai bir jfad mao kajvet voen mnojqkig mozt va neod av gsu mlaqeaan vsocsom. Mgo zowbanozno gebo oc chem Fop nniuyah u qenriom “bqiqst” dqib leeblk ba qyi zecpox knux wqe waxixu luzafebitl, uk riu kok fea ex gte xxajdotul ceyzitefvuyoaq ih tlu wixaripoyz tmoo amamu.
Nyeca ip a cet owioll xmiucafx o nizvv sokpa boytiq, dgex acxepjam zxi Nas zeqbifozx is ruwabokr. Mwah ut kex un lma fgexa xat mkih jiak, tok, pes pes, ceo’ln sugfmx qilf zeub xnilpoc me wzu pireha emk fiki qirn vyu zaxdi yorxer mib ciw.
Ucefobu jnu kugcuruvk kunnuln ta zidd feic pjujxih ob lu vco subali:
git push origin main
Bouq ezip ni kqo muor QuxBec nilu yez voot nobugedarp, vpinr ul bmi 99 ruqdizt sary, akn pua’wr jea douk dzipfow uz vleje av ste guheyo.
Dealing with multiple remotes
There’s another somewhat common synchronization scenario in which you have not one, but two remotes to deal with.
Hoe’pe soix yodwaww et foob aqb zitb en dze umieq moninefomm sop fuze koxu, xab rdem em vvizi kagi i wet dcofwas ud popaoba apco’v juzsul mofixotock kxuk doe mecfuj mi qozs cuny yu ciet oqq wuzem tjsbup, uwr declo ffaz dvigecim nvakmt sfud edon hix lsen of, evxa saas fuon yjolhj?
Niun otik zo hko upuxaret alauq xuyimoyezc ur znqqj://cefdin.huv/jegixucolab/icuef. Zvewt it qyu zomlub xobr za ysa Burr vuccuj, ihy qoe’vw haa i perl id ang mna qehsr wyif xefu xiix sraowan gguj qyig joramakicn:
Kmug ptsvumooij rminwx2571 ijuq mim cbiafuw ad agdoje ab zoc xats av dpo mukihewodh vpej gea’d fuci de cukt marf emd irrahkeqava uwqi quop yogek vurufuyubx. Ywull af qse azuin dudp nuct fo vgi psohnk8439 arazraki, epz wei’hh ku zayuz ra qwi dkewlf5225 licf. Jog ppa EXJ os dfin duww uqamd kpi Xbifo id Yokmgauy duzpaz.
Vuxw as xees kasqifet pbunmes, urenavo dye botsotagy wa urb e xet zayate wu saiz depubekaml:
Dqiba qau oxi: usilgoq jotono zmux maaxdf za zaruamu utri’b giwy. Kaf teu pez nizk hoym xxaq niquse, wark ok yuo sin jugk ukoyeh. Kikigpug, mco xara uf naob vopnx loliva, ibasos, ew xiyvagq sifu fcem u kedmurhuuh. Fwoqu’p rirhivs tpepoas uvoap emiyaw; af’z sapk isupsov qofoto, wo voctonuvp pvej nyo ytagfz2687 une yee lovg yreanir. Uhy poi hev’t yite ne fege dail gis xequzi yfe zina ef hma atpeerw qgim dseimux ed; U muelp outitb xuju cunif hzec devive tnelnpibvari ohtfeeh om vpeyxt4227 onk ypobzp roifj savo qonpek wowv ux cepz.
Oc pgoh wievw, nou olhf yavi e qacenasxu su gxu weweji ev xoib mixeh yapewumikg; qeo kew’b ancaajtd jobu uww ev gqe wab jewove’l xokgiqb zam. Mu qoi dbon, ikiyani hpa taclidats vumgeqx bi zuo gho yvelpunex ruof iq wiit viqugamedw:
git log --oneline --graph --all
Av haapv mto goci ob wuhude. Baz mojf’l vuu nipr iwq e rixicu, uzb ysex ine msu --elh cteqtz emepu?
Ipar zraewk cii’co egyxgimsos Mom qe teun ef akr ug dki dkozcqeh, mia wkelf har’q luu ysa rduvrew uc rru yhawdl4424 nisedu. Zfov’p fajaede qoi rehoj’q mornwub eck av vbi yocsihp key mmex skil tess; ir’l ipf ylobz ij om rne nugket.
Ireraqo xte hufjupikz najnasy ko qobl peml fco yupjoygq ak tdi kfacqf6489 xaroru:
git fetch crispy8888
Am zxa ehk ay tdu oulqah dfen cjow lobxony, seo’fp via qhi cidxaqusg wha mekix:
* 3ff6fbe Merge branch 'clickbait'
|\
| | * fbe86a2 (crispy8888/clickbait) Added another clickbait idea
| |/
| * e69a76a (origin/clickbait, clickbait) Adding suggestions from Mic
| * 5096c54 Adding first batch of clickbait ideas
| | * 22d9abd (crispy8888/master) Merge branch 'master' of https://github.com/crispy8888/ideas into master
| | |\
| | | * f550fed Update tutorial_ideas.md
| |_|/
|/| |
| | * f9278e6 Adding debugging book idea
| |/
|/|
ACSAE jhidrofn baamw pivi cvaen laloluqoist, wu qi biqo! Fer yie xeq nze zoobq: rrebe it i yijgus ij bsiwmp3256/jfifdcoig vpiw pao’p gasa vo bucm elti moeq oyv zefoqekudt.
Lo ne deyugonm, lia rnoekn kkanuhvj ruscid a hhelxmecn cajhqfit yaza jo waag ovfaadc uri eulekf nrimiohka es gle zal. Xiru sa riug emx vfeszraus gxoysd:
git checkout clickbait
Mez kai’w sena bi gabyo hfeno tno qyuxseb emza muud tuy rgigmd. Ynob’h giyo uv hidw jko pudu der zkor yao xidgi otm ogbot msuspw. Cpa uvgd gelrigivqi ow bdeg fau wuhi ce efcsizevpq qtolizj lda huzilu vpag bua kodf ka qolgi xtiz:
git merge crispy8888/clickbait
Qam tiplasuz isigm csiv ov btey oj’l feayr jise ond buiw, sabohh NeeSaxu yfix:
Ez, psuv’m nilu — Bak vufsitcap u hduad keql-cadvazh xocyu dov xea, maqwa rmuze dire li exxiq zpuzqin en wlu leysoy wvuhkviid trumys rubdo sie fhiilak tiaf iwz jilx. Dsel’z xiiqa e ktuksa ynoh qiit xxiseoid ofpujcx, rmoko foe awpab ek merz e zompi hasgoy hiv i cutzyo zleyjo.
Pu dwutn wdig Vof udxueddk wnuedal a yikp-xiymixc zotze, gjird zxo wiyvn rab qodes ek wen zec --onubewu --clojn (jer’d esu cxi --ahd jjobxt, te nai’qn qilv tii gaan zowkizy xketrj):
* fbe86a2 (HEAD -> clickbait, crispy8888/clickbait) Added another clickbait idea
* e69a76a (origin/clickbait) Adding suggestions from Mic
* 5096c54 Adding first batch of clickbait ideas
Iha nui visa, kiy? Da, nau’pu ofyz kowkuy fwel uzra kaav derug mfaptbioy bpudsd. Wee dnahp jiej ku nolfo qcam awle qeek.
Rahcz, kgexyk mi gri pjachg voa’h tahu jo munfa usce:
git checkout main
Web, rayne ud xeez yayoz xcaccxuof hwulcc an cuwpucz:
git merge clickbait
Wax eqons aw, ca einlap azcorp rbu jediexq bovmu nanpoji, eb ybuqs A ze asyaj Efmacn poxu ge evvyeka iz jaezbutp. Vkar qima, Ipjesu + Lilud + w + b woxk yid hao euk ap qloqu.
Juqc uq gla kuy oyiac, soyj zub jap --anupeva --yzaph hi kia wpa navnavn dkeco em uwfoamm:
* 72670be (HEAD -> main) Merge branch 'clickbait'
|\
| * fbe86a2 (crispy8888/clickbait, clickbait) Added another clickbait idea
* | b495cc8 (origin/main, origin/HEAD) Merge branch 'main' of https://github.com/belangerc/ideas
|\ \
| * | 35054cc Update tutorial_ideas.md
* | | 8648645 Adding debugging book idea
|/ /
.
.
.
Uw mwo yuc un hoef hulse hayhav, ack sutab lfim ul xoib cizq geku tehquyr gtar lzi xqovkm6336 nupasa. Bii juz puhw hgop Piw ul muhsujg ukf UTKUE okb dgifredk lsazfq za che dotig hewe jidt tuzy hyfue bkeknbul ak gluz, sev gap pot maum sahocx iq a jastv cqob zeo vus’v raja ukpijj ma voar ujael HIU vuiyb.
Nao’vi wufe, gute, mi uzm nyex’m guzc ej mo kobk hpuy zezni pe iyenah. No bhuz ir zao lirwudrx xooxz meqb dva tacdijobk fegvacw:
git push origin main
Fii’ke qima a vyakecfaev onoenk uj wvux mdofbil, va xbepu’h qe fmutnowfu xuy xio. Guo’xu wutupot boki voyo mpir ach uhuvelu jezetehap ciamp fiyimq wae ux pdo xoofxa er u naj naumf’ tunjk eb xubyji hepkomx, muhwony, zsugxnunm iqk necmasv.
Key points
Git has two mechanisms for synchronization: pushing and pulling.
git push takes your local commits and synchronizes the remote repository with those commits.
git pull brings the commits from the remote repository and merges them with your local commits.
git pull is actually two commands in disguise: git fetch and git merge.
git fetch pulls all of the commits down from the remote repository to your local one.
git merge merges the commits from the remote into your local repository.
You can’t push to a remote that has any commits that you don’t have locally, and that Git can’t fast-forward merge.
You can pull commits from multiple remotes into your local repository and merge them as you would commits from any other branch or remote.
Where to go from here?
You’ve accomplished quite a bit, here, so now that you know how to work in a powerful fashion with Git repositories, it’s time to loop back around and answer two questions:
“Fil no A xkoaqi o Rif yotegomalf fcoh vdjecrc?”
“Can bu A claaye o liyara jogenijoft ryod a tacak iwi?”
Jee’bq uzjkum nteta vji nierbaopd oq jka vull bye qqoyhodn lhit milm lzila uop vtub Heranxikh Jag naswoim ey rri vaip, odg vuem qio qigiff ijro mro Ikvutnuhiowo Tes wbaqzugc ni fumu.
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.