Naučili ste se Git naredbe, ali želite razumjeti kako kontinuirana integracija (Continuous Integration, CI) funkcionira u stvarnosti? Ili možda želite optimizirati svoje svakodnevne aktivnosti? Ovaj tečaj će vam pružiti praktične vještine kontinuirane integracije koristeći repozitorij na GitHub-u. Ovaj tečaj nije zamišljen kao neki čarobnjak koji možete jednostavno kliknuti, naprotiv, radit ćete iste aktivnosti koje ljudi zapravo rade na poslu, na isti način na koji to oni rade. Objašnjavat ću teoriju dok prolazite korake koji se odnose na nju.
Što ćemo raditi?
Kako napredujemo, postupno ćemo kreirati popis tipičnih CI koraka, što je odličan način za pamćenje tog popisa. Drugim riječima, stvorit ćemo popis radnji koje programeri poduzimaju prilikom provođenja kontinuirane integracije. Također ćemo koristiti jednostavan skup testova kako bismo naš CI proces približili stvarnom.
Ovaj GIF ilustrira commitove u vašem repozitoriju dok napredujete tečajem. Kao što vidite, nema tu ništa komplicirano, samo najvažnije.

Proći ćete kroz standardne CI scenarije:
- Rad na značajci;
- Primjena automatskih testova za osiguranje kvalitete;
- Implementacija prioritetnog zadatka;
- Rješavanje sukoba prilikom spajanja grana (merge conflict);
- Pojava greške u produkcijskom okruženju.
Što ćete naučiti?
Moći ćete odgovoriti na sljedeća pitanja:
- Što je kontinuirana integracija (CI)?
- Koje vrste automatskih testova se koriste u CI i na koje radnje se pokreću?
- Što je pull request i kada su potrebni?
- Što je razvoj vođen testovima (Test Driven Development, TDD) i kako se odnosi na CI?
- Provoditi merge ili primijeniti promjene (rebase)?
- Vratiti ili popraviti u sljedećoj verziji?
Isprva sam svugdje prevodio izraze kao što su "pull request", ali na kraju sam odlučio povratiti fraze na engleski na nekim mjestima kako bih smanjio ludilo u tekstu. Ponekad ću koristiti "programerski žargon" poput čudnog glagola "zakommitati" tamo gdje ga ljudi zapravo koriste na poslu.
Što je kontinuirana integracija?
Kontinuirana integracija, ili CI, je tehnička praksa koja se sastoji od toga da svaki član tima integrira svoj kod u zajednički repozitorij barem jednom dnevno, pri čemu rezultantni kod mora biti sposoban za kompilaciju bez grešaka.
Postoje nesuglasice oko ovog termina
Predmet spora je učestalost integracije. Neki tvrde da je spajanje koda samo jednom dnevno nedovoljno i da bi se zapravo trebalo integrirati kontinuirano. Kao primjer se navodi tim u kojem svi preuzimaju svježi kod ujutro i integriraju ga jednom uvečer. Iako je to razumna prigovor, u cjelini se smatra da je definicija "jednom dnevno" dovoljno praktična, konkretna i odgovara timovima različitih veličina.
Druga prigovor se odnosi na to da C++ davno nije jedini jezik koji se koristi u razvoju, a jednostavan zahtjev za kompilaciju bez grešaka kao način validacije je slab. Određeni set testova (npr. modulskih, koji se izvršavaju lokalno) također bi trebao uspješno završiti. Trenutno, zajednica se naginje ka tome da taj zahtjev bude obavezan, a u budućnosti bi "kompilacija + modularni testovi" mogla postati općeprihvaćena, ako to već nije.
Kontinuirana integracija razlikuje se od kontinuirane isporuke (Continuous Delivery, CD) po tome što ne zahtijeva kandidata za izdavanje nakon svakog ciklusa integracije.
Popis koraka koje ćemo koristiti tijekom kursa
- Preuzmite najnoviji kod. Stvorite granu od
master. Počnite raditi. - Kreirajte izmjene na novoj grani. Izgradite i testirajte lokalno. Je li uspješno? Idite na sljedeći korak. Ako nije, ispravite greške ili testove i pokušajte ponovo.
- Pushed u svoj udaljeni repozitorij ili udaljenu granu.
- Stvorite zahtjev za povlačenje. Raspravite o promjenama, dodajte još izmjena kako diskusija bude trajala. Učinite testove uspješnima na grani s funkcijom.
- Spojite/rebazirajte izmjene iz mastera. Učinite testove uspješnima na rezultatu spajanja.
- Implementirajte s grane funkcije na proizvodnju.
- Ako je sve u redu u proizvodnji tokom nekog razdoblja, spojite izmjene u master.

️ Priprema
Provjerite imate li potrebni softver
Da biste prošli ovaj tečaj, trebat će vam i .
Možete koristiti bilo koji Git klijent, ali ću davati naredbe samo za komandnu liniju.
Provjerite imate li instaliran Git klijent koji podržava komandnu liniju
Ako još niste instalirali Git klijent koji podržava komandnu liniju, možete pronaći upute za instalaciju .
Pripremite repozitorij
Trebate stvoriti osobnu kopiju(fork) na GitHubu. Dogovorimo se da nazivamo ovu osobnu kopiju repozitorijem tečaja.
Jeste li to učinili? Ako niste mijenjali zadane postavke, vaš tečajni repozitorij vjerojatno se zove continuous-integration-team-scenarios-students, nalazi se u vašem GitHub računu, a URL izgleda ovako
https://github.com//continuous-integration-team-scenarios-studentsNazvat ću ovu adresu jednostavno <URL репозитория>.
Okrugli zagrade kao
<тут>znače da trebate zamijeniti takav izraz odgovarajućom vrijednošću.
Provjerite da su GitHub akcije omogućene za ovaj tečajni repozitorij. Ako nisu uključene, molim vas uključite ih klikom na veliki gumb u sredini stranice, do kojeg možete doći klikom na Akcije u GitHub sučelju.
Nećete moći proći tečaj slijedeći moje upute ako GitHub Akcije nisu omogućene.

Uvijek možete koristiti mogućnost GitHuba za prikazivanje Markdowa kako biste vidjeli trenutno stanje popisa koji sastavljamo ovdje
https://github.com//continuous-integration-team-scenarios-students/blob/master/ci.mdO odgovorima
Iako je najbolji način da završite tečaj raditi sve samostalno, mogu se pojaviti i poteškoće.
Ako osjećate da ne razumijete što raditi i ne možete nastaviti, možete zaviriti u granu solution, koja postoji u vašem početnom repozitoriju.
Molim vas, ne radite spajanje solution u master tijekom tečaja. Možete koristiti ovu granu kako biste shvatili što raditi, ili kako biste usporedili svoj kod s autorovim, koristeći sve mogućnosti koje nam Git pruža. Ako ste se skroz izgubili, možete potpuno zamijeniti svoju granu master s granom solution i zatim resetirati svoj radni direktorij na onaj korak tečaja koji vam je potreban.
Koristite ovo samo ako vam je to zaista potrebno
Commitajte svoj kod
git add .
git commit -m "Backup mog rada"Ove komande
- preimenuju
masterumaster-backup; - preimenuju
solutionumaster; - prebacuju(checkout) na novu granu
masteri prepisuju sadržaj radnog direktorija; - stvaraju granu "solution" iz "master" (koja je ranije bila "solution") u slučaju da vam u budućnosti zatreba grana "solution".
git branch -m master master-backup
git branch -m solution master
git checkout master -f
git branch solutionNakon ovih radnji možete koristiti git log master da biste utvrdili koji commit vam je potreban.
Možete resetirati svoj radni direktorij na ovaj commit ovako:
git reset --hardAko ste zadovoljni rezultatom, u nekom trenutku ćete morati objaviti svoju verziju repozitorija na udaljeni repozitorij. Ne zaboravite izričito navesti udaljenu granu kada to radite.
git push --force origin masterMolimo obratite pažnju da koristimo git push --force. Vjerojatno nećete često htjeti tako postupati, ali ovdje imamo izuzetno specifičan scenarij s jednim korisnikom repozitorija koji uz to zna što radi.
Započnimo s radom

Zapocinje sastavljanje našeg popisa koraka CI. Obično ovaj korak započinjete povlačenjem najnovije verzije koda iz udaljenog repozitorija, ali još uvijek nemamo lokalni repozitorij, pa umjesto toga kloniramo iz udaljenog.
️ Zadatak: ažurirajte lokalni repozitorij, stvorite granu iz master, započnite raditi
- Klonirajte repozitorij tečaja iz
<URL репозитория>. - Pokrenite
npm installu direktoriju repozitorija tečaja; potreban nam je za instalaciju Jesta, kojeg koristimo za pokretanje testova. - Stvorite granu i nazovite je
feature. Prebacite se na ovu granu. Dodajte testni kod u
ci.test.jsizmeđu komentara s molbom da se to učini.it('1. povući najnoviji kod', () => { expect(/.*pull.*/ig.test(fileContents)).toBe(true); }); it('2. dodaj commit-e', () => { expect(/.*commit.*/ig.test(fileContents)).toBe(true); }); it('3. gurni na udaljenu granu s istim imenom', () => { expect(/.*push.*/ig.test(fileContents)).toBe(true); }); it('4. stvori pull request i nastavi raditi', () => { expect(/.*pulls+request.*/ig.test(fileContents)).toBe(true); });- Dodajte tekst s prva 4 koraka u datoteku
ci.md.1. Povuci najnoviji kod. Stvori granu iz `master`. Započni rad. 2. Stvori commit-e na svojoj novoj grani. Izgradi i testiraj lokalno. Prošlo? Idite na sljedeći korak. Ne? Ispravite greške ili testove i pokušajte ponovo. 3. Gurni na svoj udaljeni repozitorij ili udaljenu granu. 4. Stvori pull request. Raspravljaj o promjenama, dodaj više commit-a dok rasprava traje. Osiguraj da testovi prolaze na grani s funkcionalnostima.Naredbe
# Клонируйте репозиторий курса
git clone <repository URL>
cd <repository name>
# Выполните npm install в каталоге репозитория курса; он установит Jest, который мы используем для запуска тестов.
npm install
# Создайте ветку и назовите ее feature. Переключитесь на эту в ветку.
git checkout -b feature
# Отредактируйте ci.test.js как описано выше.
# Отредактируйте ci.md как описано вышеStvarajte commit-e u novoj grani, gradite i testirajte lokalno
Planiramo postaviti testove da se pokreću prije commita, a zatim commitati kod.
Uobičajeni scenariji kada se testovi pokreću automatski
- Lokalno:
- Neprekidno ili kao odgovor na relevantne promjene koda;
- Prilikom spremanja (za interpretirane ili JIT-kompajlirane jezike);
- Prilikom izgradnje (kada je potrebno prevesti);
- Prilikom commita;
- Prilikom objavljivanja javnom repozitoriju.
- Na serveru za izgradnju (build server) ili u okruženju za izgradnju:
- Kada se kod objavljuje u osobnu granu / repozitorij.
- Kod se testira u toj grani.
- Testira se potencijalni rezultat spajanja (obično s
master). - Kao dio kontinuirane integracije / kontinuiranog isporučivanja
Općenito, što je brži set testova, to ga češće možete pokretati. Tipična raspodjela po fazama može izgledati ovako.
- Brzi modularni testovi — pri izradi, u CI cjevovodu
- Sporiji modularni testovi, brzi komponentni i integracijski testovi — pri commitu, u CI cjevovodu
- Sporiji komponentni i integracijski testovi — u CI cjevovodu
- Testiranje sigurnosti, opterećenja i drugi dugotrajni ili skupi testovi — u CI/CD cjevovodima, ali samo u određenim režimima / fazama / cjevovodima izrade, na primjer, prilikom pripreme kandidata za izdanje ili pokretanja ručno.
️ Zadatak
Predlažem da prvo ručno pokrenemo testove koristeći naredbu npm test. Nakon toga dodajmo git hook za pokretanje naših testova prilikom commita. Ima jedna caka: Git hookovi se ne smatraju dijelom repozitorija i stoga se ne mogu klonirati s GitHub-a zajedno s ostalim materijalima tečaja. Da biste postavili hook, trebate pokrenuti install_hook.sh ili kopirati datoteku repo/hook/pre-commit u lokalni direktorij .git/hooks/.
Prilikom commita vidjet ćete kako se testovi izvode i provjeravaju da li su određene ključne riječi prisutne na popisu.
- Pokrenite testove ručno, izvršavajući naredbu
npm testu mapi repozitorija vašeg tečaja. Pobrinite se da su testovi provedeni. - Postavite hook za commit (pre-commit hook) pokretanjem
install_hook.sh. - Napravite commit promjena u lokalni repozitorij.
- Pobrinite se da se testovi izvršavaju prije commita.
Vaš repozitorij trebao bi izgledati ovako nakon izvršavanja ovih radnji.

Naredbe
# Установите pre-commit hook выполнив install_hook.sh.
# Закоммитьте изменения в локальный репозиторий. Используйте "Add first CI steps" в качестве сообщения при коммите.
git add ci.md ci.test.js
git commit -m "Add first CI steps"
# Убедитесь, что тесты запускаются перед коммитом. Objavite kod u udaljeni repozitorij ili udaljenu granicu
Nakon što završe s lokalnim radom, programeri obično svoje kodove učine javno dostupnima kako bi se na kraju mogli integrirati s zajedničkim. Uz GitHub, to se obično postiže objavljivanjem rada ili u osobnoj kopiji repozitorija (personal fork, fork) ili u osobnoj grani.
- Kada se koriste forkovi, programer klonira udaljeni javni repozitorij, stvarajući svoju osobnu udaljenu kopiju, poznatu kao fork. Nakon toga, klonira ovaj osobni repozitorij kako bi radio s njim lokalno. Kada je rad završen i dodaci su napravljeni, smješta ih u svoj fork, gdje su dostupni drugima i mogu se integrirati u zajednički repozitorij. Ovaj pristup obično se koristi u projektima s otvorenim izvorom na GitHubu. Također se koristi u mom naprednom tečaju [Team Work and CI with Git]).
- Drugi pristup je koristiti samo jedan udaljeni repozitorij i smatrati samo grananje
masterzajedničkog repozitorija "zaštićenim". U ovom scenariju pojedinačni programeri objavljuju svoj kod u granama udaljenog repozitorija, kako bi drugi mogli pregledati taj kod; ako je sve u redu, spajaju smasterzajedničkog repozitorija.
U ovom konkretnom tečaju koristit ćemo radni proces koji koristi grane.
Objavimo naš kod.
️ Zadatak
- Objavite promjene u udaljenoj grani s istim imenom kao vaša radna grana
Naredbe
git push --set-upstream origin featureIzradite pull request
Izradite pull request s nazivom Steps review. Postavite feature kao "head branch" i master kao "base branch".
Pobrinite se da ste postavili
masteru svom fork repozitorija kao "base branch"; neću razmatrati zahtjeve za promjenama u repozitorij s materijalima tečaja.
Na slengu GitHub-a, "base branch" je grana na kojoj temeljite svoj rad, dok je "head branch" grana koja sadrži predložene promjene.
Razgovarajte o promjenama, dodajte nove dodatke dok se rasprava nastavlja
Pull request (PR)
Pull request (PR) je način da se raspravi i dokumentira kod, kao i da se provede pregled koda (code review). Pull request nazvani su prema uobičajenom načinu integracije pojedinačnih promjena u zajednički kod. Obično osoba klonira udaljeni službeni repozitorij projekta i radi na kodu lokalno. Nakon toga, smješta kod u svoj osobni udaljeni repozitorij i traži od odgovornih za službeni repozitorij da preuzmuomogućuju objavu artefakata ili preuzimanje postojećih artefakata iz udaljenog registra. Pokušajmo objaviti politiku koju smo stvorili u lokalni Docker registar pomoću) njegov kod u svoje lokalne repozitorije, gdje ga pregledavaju i, možda, integrirajumerge) ga. Ova koncepcija poznata je i pod drugim nazivima, na primjer, merge request.
Zapravo, nije potrebno koristiti funkciju pull request na GitHubu ili sličnim platformama. Timovi programera mogu koristiti druge načine komunikacije, uključujući osobne razgovore, telefonske pozive ili e-poštu, ali postoje brojni razlozi zašto koristiti pull requestove kao oblik rasprave. Evo nekoliko od njih:
- organizirane rasprave vezane uz specifične izmjene u kodu;
- kao mjesto za pregled povratnih informacija o nedovršenom radu, kako od automatskih testova, tako i od kolega;
- formalizacija provjera koda;
- kako bi se kasnije mogli razjasniti razlozi i razmišljanja koja stoje iza određenog dijela koda.
Obično kreirate pull request kada trebate nešto raspraviti ili dobiti povratnu informaciju. Na primjer, ako radite na funkciji koja se može implementirati na više načina, možete otvoriti zahtjev za promjenu čak i prije nego što napišete prvu liniju koda, kako biste podijelili svoje ideje i raspravljali o svojim planovima s koautorima. Ako je rad jednostavniji, pull request se otvara kada je nešto već učinjeno, zabilježeno i može se raspraviti. U nekim scenarijima možete otvoriti PR samo iz razloga kontrole kvalitete: kako biste pokrenuli automatske testove ili inicirali provjeru koda. Što god odlučili, ne zaboravite @spomenuti ljude čije odobrenje je potrebno u vašem pull requestu.
Obično, kada kreirate PR, radite sljedeće.
- Navedite što predlažete promijeniti i gdje.
- Napišite opis koji objašnjava svrhu izmjena. Možda biste željeli:
- dodati nešto važno što nije očito iz koda, ili nešto korisno za razumijevanje konteksta, na primjer, povezane #greške i brojeve commitova;
- @spomenuti sve s kojima želite započeti suradnju, ili ih možete @spomenuti u komentarima kasnije;
- zatražiti pomoć kolega s nečim ili provjeru nečega konkretnog.
Nakon što otvorite PR, pokreću se testovi koji su postavljeni da se izvršavaju u tim slučajevima. U našem slučaju, to će biti isti set testova koje smo pokretali lokalno, ali u pravom projektu mogu postojati dodatni testovi i provjere.
Molimo vas, pričekajte dok testovi završe. Status testova možete vidjeti na dnu rasprave PR u interfejsu GitHub. Nastavite kada testovi budu završeni.
️ Dodajte napomenu o proizvoljnosti popisa koraka CI
Popis korišten u ovom tečaju je proizvoljan i subjektivan, trebamo dodati napomenu o tome.
️ Zadatak: kreiranje pull requesta za ovu napomenu
- Prebacite se na granu
master. - Kreirajte granu s imenom
bugfix. - Dodajte tekst napomene na kraj datoteke
ci.md.> **GitHub flow** se ponekad koristi kao nadimak za varijantu razvoja temeljenog na trunku kada se kod postavlja izravno iz grana značajki. Ovaj popis je samo interpretacija koju koristim u svojim [DevOps tečajevima](http://redpill.solutions). Službeni vodič je [ovdje](https://guides.github.com/introduction/flow/). - Zakažite promjene.
- Objavite granu
bugfixna udaljeni repozitorij. - Kreirajte pull request s imenom Dodavanje napomene s glavnom granom
bugfixi osnovnom granommaster.
Pobrinite se da ste postavili
masteru svom fork repozitorija kao "base branch"; neću razmatrati zahtjeve za promjenama u repozitorij s materijalima tečaja.
Evo kako bi vaš repozitorij trebao izgledati.

Naredbe
# Переключитесь на ветку master. Создайте ветку bugfix.
git checkout master
# Создайте ветку bugfix-remark.
git checkout -b bugfix
# Добавьте текст примечания внизу ci.md.
# Закоммитьте изменения
git add ci.md
git commit -m "Add a remark about the list being opinionated"
# Опубликуйте ветку bugfix в удалённый репозиторий.
git push --set-upstream origin bugfix
# Создайте pull request при помощи интерфейса GitHub как описано вышеOdobrite pull request "Dodavanje napomene"
️ Zadatak
- Kreirajte pull request.
- Kliknite "Spoji pull request".
- Kliknite "Potvrdi spajanje".
- Kliknite "Izbriši granu", više nam nije potrebna.
Ovo je dijagram komita nakon spajanja.

️ Nastavite raditi i dodavati testove
Suradnja na pull requestu često dovodi do potrebe za dodatnim radom. Obično je to rezultat revizije koda ili rasprave, ali u našem tečaju simulirat ćemo to dodajući nove stavke u naš popis koraka CI.
U kontinuiranoj integraciji obično se primjenjuje određeno testno pokriće. Zahtjevi za pokrićem testovima variraju i obično se nalaze u dokumentu s naslovom poput "vodič za autore" (contribution guidelines). Postupit ćemo jednostavno i dodati po jedan test za svaki redak u našem kontrolnom popisu.
Kada izvršavate zadatke, prvo pokušajte zakompitirati testove. Ako ste ispravno postavili pre-commit hook ranije, tek dodani test će se pokrenuti, neće proći i ništa neće biti zakompitirano. Imajte na umu: tako saznajemo da naši testovi zaista nešto provjeravaju. Zanimljivo je da, ako bismo počeli s kodom prije testova, prolaznost testova mogla bi značiti ili da kod radi kako se očekuje, ili da testovi zapravo ništa ne provjeravaju. Osim toga, ako ne bismo napisali testove u prvom redu, mogli bismo ih potpuno zaboraviti, jer nam ništa ne bi pripominjalo o tome.
Razvoj kroz testiranje (TDD)
TDD preporučuje pisanje testova prije koda. Uobičajeni radni proces korištenja TDD-a izgleda ovako.
- Dodajte test.
- Pokrenite sve testove i uvjerite se da novi test ne prolazi uspješno.
- Napišite kod.
- Pokrenite testove, provjerite jesu li svi testovi prošli uspješno.
- Izvršite refaktoring koda.
- Ponovite.
Budući da rezultati testova koji nisu prošli uspješno obično su prikazani crvenom, a uspješni zelenom, ciklus je također poznat kao "crveno-zeleno-refaktoring".
️ Zadatak
Prvo pokušajte napraviti commit testova i dopustite im da ne uspiju, zatim dodajte i commitajte tekst popisa CI koraka. Vidjet ćete kako testovi prolaze ("zeleni").
Zatim objavite novi kod na udaljeni repozitorij i gledajte kako se testovi provode u sučelju GitHub na dnu rasprave o zahtjevu za povlačenje, a status PR se ažurira.
- Prebacite se na granu
feature. Dodajte te testove u
ci.test.jsposlije zadnjeg pozivait (...);.it('5. Spojiti/rebase-ati commit-ove s mastera. Osigurati da testovi prolaze na rezultatu merge-a.', () => { expect(/.*merge.*commits.*testss+pass.*/ig.test(fileContents)).toBe(true); }); it('6. Uvesti s feature grane u produkciju.', () => { expect(/.*Deploy.*tos+production.*/ig.test(fileContents)).toBe(true); }); it('7. Ako je sve dobro u produkciji tijekom nekog razdoblja vremena, spojite promjene s masterom.', () => { expect(/.*merge.*tos+master.*/ig.test(fileContents)).toBe(true); });- Pokušajte napraviti commit testova. Ako
pre-commithook je postavljen, pokušaj commit-a će završiti greškom. - Zatim dodajte ovaj tekst u
ci.md.5. Spojiti/rebase-ati commit-ove s mastera. Osigurati da testovi prolaze na rezultatu merge-a. 6. Uvesti s feature grane s tajnim bugom u produkciju. 7. Ako je sve dobro u produkciji tijekom nekog razdoblja vremena, spojite promjene s masterom. - Izvršite i commitajte promjene lokalno.
- Objavite promjene u granu
feature.
Sada bi trebali imati nešto poput ovoga

Naredbe
# Переключительна ветку feature
git checkout feature
# Добавить тесты в ci.test.js как описано выше
# Добавьте в индекс ci.test.js чтобы позже закоммитить
git add ci.test.js
# Попытайтесь закоммитить тесты. Если pre-commit hook установлены, коммит не произойдёт.
git commit
# Теперь добавьте текст в ci.md как описано выше
# Внесите изменения и закоммитьте их
git add ci.md
git commit -m "Add the remaining CI steps"
# Опубликуйте изменения в ветку feature
git pushSukob tijekom spajanja
Idite na zahtjev za povlačenje Steps review.
Iako nismo učinili ništa loše, i testovi za naš kod su prošli uspješno, još uvijek ne možemo izvršiti spajanje grane feature i master. To je zato što je druga grana bugfix bila spojena s master dok smo radili na ovom PR-u.
To stvara situaciju gdje udaljena grana master ima noviju verziju od one na kojoj smo bazirali granu feature. Zbog toga ne možemo jednostavno vratiti HEAD master do kraja grane feature. U ovoj situaciji trebamo ili izvršiti spajanje (merge), ili primijeniti commit-e feature na vrhu (rebase) masterGitHub zapravo može izvršiti automatsko spajanje ako nema sukoba. Nažalost, u našoj situaciji obje grane imaju konkurentske izmjene u datoteci ci.mdOva situacija je poznata kao sukob pri spajanju (merge conflict) i trebamo je riješiti ručno.
Merge ili rebase
Merge
- Stvara dodatni merge commit i zadržava povijest rada.
- Zadržava izvorne commit-e grana s izvorim vremenskim oznakama i autorima.
- Zadržava SHA commit-a i reference na njih u diskusijama o zahtjevima za promjene.
- Zahteva jednokratno rješavanje sukoba.
- Čini povijest nonlinearom.
- Povijest može biti teška za čitanje zbog velikog broja grana (podsjeća na IDE kablove).
- Onemogućava automatsko debagiranje, na primjer, čini
git bisectmanje korisnim — on će samo pronaći merge commit.
Rebase
- Reproducira commit-e iz trenutne grane preko osnove jedan za drugim.
- Formiraju se novi commiti s novim SHA, što rezultira time da se commit-i u GitHub-u odnose na izvorne pull zahtjeve, ali ne na odgovarajuće komentare.
- Commit-i se mogu rekombinirati i izmijeniti tijekom procesa ili čak spojiti u jedan.
- Može biti potrebno riješiti nekoliko sukoba.
- Omogućuje održavanje linearne povijesti.
- Povijest može biti lakša za čitanje, osim ako nije previše dugačka bez razumnih razloga.
- Automatsko debagiranje i rješavanje problema su donekle lakši: omogućuje
git bisect, može učiniti automatske povratke jasnijima i predvidljivijima.
- Potrebno je objavljivanje grane s premještenim commit-ima s oznakom
--forceprilikom korištenja s zahtjevima za promjene.
Obično timovi pristaju uvijek koristiti istu strategiju kada trebaju kombinirati promjene. To može biti "čista" fuzija ili "čisto" primjena commit-a iznad ili nešto posredno, kao što je izvođenje primjene commit-a iznad u interaktivnom režimu (git rebase -i) lokalno za grane koje nisu objavljene u zajedničkom repozitoriju, ali spajanje za "javne" grane.
Ovdje ćemo koristiti spajanje.
️ Zadatak
- Provjerite da je kod u lokalnoj grani
masteražuriran iz udaljenog repozitorija. - Prebacite se na granu
feature. - Pokrenite spajanje s granom
master. Bit će obaviješteno o sukobu spajanja vezanom uz konkurentske izmjene uci.md. - Dopustite sukob tako da u tekstu ostane i naš popis koraka CI, i napomena o njemu.
- Objavite spojni commit u udaljenu granu
feature. - Provjerite status pull request-a u korisničkom sučelju GitHuba, pričekajte da se spajanje okonča.
Naredbe
# Убедитесь, что код в локальное ветке `master` обновлён из удалённого репозитория.
git checkout master
git pull
# Переключитесь на ветку feature
git checkout feature
# Инициируйте слияние с веткой master
git merge master
# A merge conflict related to concurrent changes to ci.md will be reported
# => Auto-merging ci.md
# CONFLICT (content): Merge conflict in ci.md
# Automatic merge failed; fix conflicts and then commit the result.
# Разрешите конфликт так, чтобы и наш список шагов CI, и замечание о нем остались в тексте.
# отредактируйте ci.md чтоб он не содержал маркеров конфликта слияния
git add ci.md
git merge --continue
# при коммите можете оставить сообщение по умолчанию
# Опубликуйте коммит слияния в удаленную ветку feature.
git push
# Проверьте статус запроса на изменения в пользовательском интерфейсе GitHub, дождитесь пока слияние не будет разрешено.Odličan posao!
Završili ste s popisom, a sada trebate odobriti pull request u master.
️ Zadatak: Odobrite pull request "Pregled koraka"
- Otvorite pull request.
- Kliknite "Spoji pull request".
- Kliknite "Potvrdi spajanje".
- Kliknite na "Obriši granu", jer nam više nije potrebna.
To je vaš repozitorij u ovom trenutku

Greška u produkciji
Kažu da "testiranje može pokazati prisutnost grešaka, ali nikad ne može pokazati njihovu odsutnost." Iako smo imali testove koji nisu prikazali nikakve greške, podla greška se ušuljala u produkciju.
U sličnom scenariju moramo voditi računa o:
- onome što je implementirano u produkciji;
- kod koji je na grani
masters greškom, s kojeg programeri mogu započeti novi posao.
Vratiti ili ispraviti u sljedećoj verziji?
"Vraćanje" (rolling back) je implementacija unaprijed ispravne ranije verzije u produkcijsko okruženje i opoziv (revert) commitova koji sadrže grešku. "Ispravka u sljedećoj verziji" (fixing forward) je dodavanje ispravke u master i implementacija nove verzije što je prije moguće. Kako se API i sheme baza podataka mijenjaju prilikom implementacije koda u produkcijsko okruženje, kod kontinuirane isporuke i dobrog pokrivanja testovima, vraćanje je obično mnogo složenije i rizičnije od ispravke u sljedećoj verziji.
Budući da vraćanje ne nosi nikakvu opasnost u našem slučaju, krenut ćemo tim putem, jer nam to omogućuje
- da ispravimo grešku u produkciji što je prije moguće;
- da kod u
masterodmah bude spreman za započinjanje novog posla.
️ Zadatak
- Prebacite se na granu
masterlokalno. - Ažurirajte lokalni repozitorij iz udaljenog repozitorija.
- Opozovite spojni commit PR-a Steps review u
master. - Objavite promjene u udaljeni repozitorij.
Ovo je povijest repozitorija s opozvanim spojnim commitom

Naredbe
# Переключитесь на ветку master.
git checkout master
# Обновите локальный репозиторий из удалённого репозитория.
git pull
# Отмените коммит слияния PR Steps review в master.
# Мы отменяем коммит слияния, поэтому нам нужно выбрать ветку истории, которую мы захотим оставить
git show HEAD
# предположим, что коммит, который был последним в ветке master до слияния, был отображён предыдущей командой первым
git revert HEAD -m 1
# можете не менять сообщения коммитов
# Опубликуйте изменения в удалённый репозиторий
git push️ Samo-provjera
Osigurajte da ci.md više ne sadrži tekst "sneaky bug" nakon opoziva spojnog commita.
Ispravite popis koraka CI i vratite ga u master
Potpuno smo opozvali spojni commit grane feature. Dobre vijesti su da sada nemamo grešku u masterLoša vijest je da je nestala naša dragocjena lista koraka kontinuirane integracije. Dakle, idealno bi bilo da primijenimo ispravak na commitima iz feature i vratimo ih u master zajedno s ispravkom.
Možemo pristupiti zadatku na različite načine:
- ponovno otkazati (revert) commit koji poništava spajanje
featuresmaster; - premjestiti commit-e iz bivše
feature.
Različiti razvojni timovi u ovom slučaju koriste različite pristupe, mi ćemo premjestiti korisne commit-e u novu granu i kreirati zaseban pull request za tu novu granu.
️ Zadatak
- Kreirajte granu pod imenom
feature-fixi prebacite se na nju. Premjestite sve commit-e iz bivše grane
featureu novu granu. Riješite konflikte spajanja koji su se pojavili prilikom premještanja.
Dodajte regresijski test u
ci.test.js:it('does not contain the sneaky bug', () => { expect( /.*sneakys+bug.*/gi.test(fileContents)).toBe(false); });- Pokrenite testove lokalno kako biste osigurali da ne završavaju uspješno.
- Izbrišite tekst " with a sneaky bug" u
ci.md. - Dodajte promjene testova i promjene na listu koraka u indeks i commit-ujte ih.
- Objavite granu u udaljeni repozitorij.
Na kraju biste trebali imati nešto slično

Naredbe
# Создайте ветку под названием feature-fix и переключитесь на нее.
git checkout -b feature-fix
# Перенесите все коммиты из бывшей ветки feature в новую ветку. Разрешите конфликты слияния, которые возникли при переносе.
# используйте историю чтобы узнать хэши коммитов:
# - предшествующего коммиту с первой частью списка: C0
# - добавляющего последние элементы списка: C2
git log --oneline --graph
git cherry-pick C0..C2
# разрешите конфликты слияния
# - отредактируйте ci.md и/или ci.test.js
# - добавьте файлы в индекс
# - выполните "git cherry-pick --continue", можете не менять сообщение коммита
# Добавьте регрессионный тест в ci.test.js
# Запустите тесты локально, чтобы убедиться, что они не завершаются успешно.
# Удалите текст " with a sneaky bug" в ci.md.
# Добавьте в индекс изменения тестов и в списке шагов и закоммитьте их.
git add ci.md ci.test.js
git commit -m "Fix the bug in steps list"
# Опубликуйте ветку в удалённый репозиторий.
git push --set-upstream origin feature-fix
Kreirajte pull request.
Izradite pull request s nazivom Fixing the feature. Postavite feature-fix kao "head branch", a master kao "base branch".
Molimo vas da pričekate dok testovi završe. Status testova možete vidjeti na dnu rasprave PR-a.
Pobrinite se da ste postavili
masteru svom fork repozitorija kao "base branch"; neću razmatrati zahtjeve za promjenama u repozitorij s materijalima tečaja.
Odobrite pull request "Fixing the feature"
Hvala na ispravljanju! Molimo odobrite promjene u master iz pull requesta.
️ Zadatak
- Kliknite "Spoji pull request".
- Kliknite "Potvrdi spajanje".
- Kliknite na "Obriši granu", jer nam više nije potrebna.
To je ono što biste trebali imati u ovom trenutku

Čestitam!
Izvršili ste sve radnje koje ljudi obično poduzimaju tijekom procesa kontinuirane integracije.
Ako primijetite bilo kakve probleme s tečajem ili znate kako ga poboljšati, otvorite issue u . Ovaj tečaj također ima koja koristi GitHub Learning Lab kao platformu.
Izvor: habr.com

