Cvičení: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.
- Než začneme …
- Průběžný příklad
- Issues v GitLabu
- Větve v Gitu (pojďme opravit chyby)
-
Propojení commitů s issue a
git commit --amend
- Nahrání (push) nové větve
- Cvičení
- Graf commitů
- Merge requests (žádosti o začlenění)
- Mergování z příkazové řádky
- Zobrazení seznamu větví a mazání větví
- Začleňování změn z upstreamu (udržování vaší větve aktuální)
- Zcela nesouvisející témata :-)
- Úlohy před cvičením (deadline: začátek vašeho cvičení, týden 27. března - 31. března)
- Úlohy po cvičení (deadline: 16. dubna)
- Učební výstupy
- Seznam změn na této stránce
Cílem tohoto cvičení je ukázat klíčovou vlastnost Gitu: větve. Je to mocný nástroj pro každodenní kódování softwaru vyvíjeného v týmu. Ale hodí se i pro jednočlenné týmy.
Dnešní software je málokdy tvořen jedinou osobou: je to týmová činnost a členové týmu potřebují spolupracovat na vývoji. Na tomto cvičení si ukážeme, co Git nabízí v tomto směru pro týmy v podstatě libovolné velikosti. Také se podíváme, jak je GitLab propojený s Gitem a jaké nástroje nabízí pro manažerskou část práce.
Obvykle týmová práce na sdíleném kódu znamená, že potřebujete, aby:
- práce každého člena týmu byla oddělená,
- ale bylo možné jednoduše výsledky jednotlivých členů kombinovat (alespoň v okamžiku, kdy jsou části skutečně nezávislé)
Tyto vlastnosti Git nabízí pomocí větví (branches). Ve skutečnosti je koncept větví mnohem silnější a hodí se i pro projekty s jedním vývojářem. V tomto cvičení se podíváme, jak se používají.
Než začneme …
Mnoho věcí, které zde zmíníme, už znáte z předchozích cvičení. To je v pořádku a je to naschvál: teď se je pokusíme představit najednou jako ucelený obrázek toho, co Git umí a jak se s ním pravděpodobně setkáte ve svých budoucích zaměstnáních.
Pokud už větve z Gitu znáte, asi si všimnete, že spousty věcí zjednodušujeme. Formálně jsou větve ukazatele na uzly acyklického grafu comittů atd., ale to skutečně není podstatné pro pochopení tohoto textu (a do detailů se tím zabývá NSWI154).
Průběžný příklad
Vytvořte fork projektu teaching/nswi177/2023/common/group-sum.
Fork je kompletní kopie repozitáře původního projektu. Při forkování se stanete vlastníkem projektu a můžete cokoliv měnit, aniž by se to dotklo původního projektu.
student-LOGIN
, kam odesíláte hodnocené úlohy, neforkujte.
Doporučujeme, abyste změnili viditelnost vašeho forku na privátní.
V průběhu celého cvičení budeme pracovat s příkladem v tomto repozitáři. Nezapomeňte naklonovat svůj fork (nikoli původní repozitář). Budete v něm provádět poměrně hodně změn.
Tento příklad se pokusí napodobit práci v týmu – kdykoli budeme mluvit o nějaké funkci (nebo chybě), představte si, že pracujete ve velkém týmu a funkce/chyby nejsou jednořádkové opravy, ale několikadenní práce jednotlivých členů týmu.
Podívejte se na implementaci uvnitř souboru group_sum.py
. Později
uvidíme, že soubor group_sum.py
by měl být v adresáři src
a projekt by
měl být správně nakonfigurován pro Pythoní program, ale zatím zůstaneme u
jednodušší varianty.
Implementace je mírně rozšířenou verzí našeho předchozího skriptu, který uměl sčítat celá čísla na základě obsahu řádku.
Především používá modul
argparse
pro lepší
parsování parametrů příkazového řádku. To nám umožnilo rozšířit funkci o
použití vlastních oddělovačů a dalších drobnosti.
Vzhledem k tomu, že celý nástroj je poměrně malý, je výpočetní jádro programu zakrslík v porovnání s konfigurací parseru voleb na příkazové řádce. Tohoto kódu se však nebojte. Parser parametrů v Pythonu je poměrně užitečný modul, který s minimálním úsilím udělá programy v Pythonu mnohem čitelnějšími (především z hlediska jejich spuštění).
Issues v GitLabu
Všimněte si, že skript se ukončí s výjimkou, pokud vstupní soubor neexistuje (místo vypsání nějaké hezké chybové zprávy).
To rozhodně není uživatelsky přívětivé. Pojďme to napravit.
Lidé však (nemá smysl to zastírat) málokdy mají čas řešit problém okamžitě. Proto je docela užitečné poznamenat si všechny nevyřešené problémy v projektu, aby se na ně nezapomnělo.
Abychom si udrželi přehled o nevyřešených problém v našich projektech, je dobré je zaznamenávat. V postranní liště každého Gitlabového projektu je odkaz na Issues: pokud na něj kliknete, uvidíte, že The Issue Tracker is the place to add things that need to be improved or solved in a project. To je to, co potřebujeme ;-).
Vytvořte nový Issue popisující problém.
Každá issue má nadpis – něco jako předmět v e-mailu –, který by měl shrnout, co je špatně nebo co se musí udělat. Také musíte dodat popis – v některých případech si můžete myslet, že nadpis Chyba když chybí soubor úplně stačí. Nestačí! Vždy přidejte příklad a postup, jak problém zreprodukovat.
Tohle platí i v případě, že hlásíte problémy se zadáním apod. nám :-).
Vraťme se k našemu příkladu. Chyby se často houfují. Problémů s kódem je více. Co se stane při následujícím vstupu:
alpha 45
charlie 32
alpha HELLO
Jejda, další výjimka.
Vytvořte proto ve svém projektu další issue. Opět: použijte popisný nadpis, uveďte smysluplný popis. Opravdu. Použijte to jako cvičení pro hodnocený úkol.
Zobrazte si seznam svých issue. Každý issue by měl mít vedle sebe číslo, na které se můžeme později odkázat.
Něco navíc
Mnohé projekty mají dokonce šablony, aby uživatele navedly, které všechny informace jsou potřeba. My je používat nebudeme, ale pro velké projekty jsou užitečné. GitLab je umí také.
Všimněte si odkazu Markdown, které obsahuje nápovědu pro formátování
pomocí Markdownu: znalost `
a
```
je prostě nutnost pro každého programátora :-).
Pro další čtení si do vyhledávače zadejte jak napsat dobrý bugreport (how to write a good bug report) a alespoň jeden článek si přečtěte. Stojí to za to. Doopravdy.
Větve v Gitu (pojďme opravit chyby)
Git má koncept větví, které reprezentují řadu commitů. Zatím byla tato řada lineární – každý commit (kromě úplně prvního a posledního, pochopitelně) měl jeden předchozí a jeden následující commit. Jejich pořadí bylo určeno tím, jak commity vznikaly v čase.
Větve v Gitu vám umožní tuto linearitu rozbít – commit může mít více následníků: práce se rozdělí a každá větev má svou vlastní cestu: do programu přidáváme nové funkce. Commit také může mít dva rodiče: provádíme tzv. merge dvou větví (slití, spojení).
Typický příklad je práce v týmu. Alice a Bob pracují oba na stejném projektu a sdílí jeden repozitář. Alice pracuje na funkci A, Bob na funkci B. Oba začali na stejném commitu (řekněme hned po vydání poslední verze), ale jejich práce se rozchází: každý pracuje na svém úkolu a přidává své funkce. Jakmile jsou se svojí prací spokojeni, provedou tzv. merge – tj. spojí svoje verze dohromady a získají tak verzi, které obsahuje funkce A i B.
Následující obrázek ukazuje příklad jednoduchých větví (v MSIMu), ale i komplikovanější situaci ve středně velkém open-source projektu (HelenOS).
Ve skutečnosti jste už s Gitovými větvemi pracovali, aniž byste o tom
věděli.
Když uděláte clone
repozitáře, vytvoříte přesnou kopii stavu na serveru.
Když jste přidali nové commity lokálně, objevili se vlastně na větvi, která
je odlišná
od větve na serveru.
Pak push
tyto větve zase spojil.
A pull
pracuje v opačném směru: přitáhne nové commity ze serveru a připojí
je k vaší místní větvi.
Ale zatím tyto větve nikdy nedivergovaly – jedna větev byla vždy prefixem
té druhé. Takže spojování nevyžadovalo žádnou
extra činnost a bylo pro vás transparentní.
Commit zprávy (už zase)
Přečtěte si článek How to Write a Git Commit Message od Chrise Beams, pokud jste ho ještě nečetli. A pokud jste ho už četli, klidně si ho přečtěte znovu.
Fázi, kdy Git byl nepřítel, máme teď už za sebou a můžeme tedy pracovat na zlepšení našich návyků.
Od teď začněte psát rozumné commit zprávy. Jsou součástí vývoje a jsou téměř tak důležité jako kód, na který odkazují. Hlavně ve velkých týmech.
Pokud máte problém pojmenovat commit, asi se v něm děje moc věcí najednou. Je to stejné jako s funkcemi (ano, už zase!): pokud je nedokážete popsat jednou větou, něco je špatně.
Feature branches (větve pro nové funkce)
Aby se kód udržel v rozumném stavu, mnoho projektů má jednoduché pravidlo:
commitujte co nejčastěji, ale kód v hlavní větvi (tohle jméno můžete změnit,
ale obvykle se potkáte s názvy jako master
nebo main
) musí být vždy v
pořádku (ve smyslu, že všechny testy prochází).
Pokud pracujete na nové funkci, vytvořte si novou větev.
Pracujte v této větvi a spojte ji s master
em jen, když bude funkce hotová.
Pro některé projekty je povinnou částí před vlastním mergem recenze kódu
(code review) nebo dokonce zátěžové testy (load testing).
Má to skvělou výhodu: když někdo začne novou větev, můžete si být celkem jistý, že začíná s funkčním kódem.
Budeme se tím ale řídit i v tomto cvičení. Pro každou novou funkci (nebo opravu chyby) budeme mít novou větev a do hlavní větve ji zamergujeme až po otestování.
Vytváření nových větví v Gitu
Začneme opravou problému s vyhozenou výjimkou. Vytvoříme pro ni větev a přepneme se na ni.
Větší týmy mají často zavedené konvence pro pojmenování větví. Zjednodušme
si to a používejme issue/
N-jmeno
pro větve, které mají opravit problém
v issue s číslem N.
Pro vytvoření větve použijeme příkaz git branch
.
git branch issue/1-hide-traceback
K vytvoření jedinečného názvu větve používáme id issue (abychom zabránili případným kolizím s ostatními vývojáři), ale také připojujeme krátké shrnutí, abychom my sami věděli, na čem pracujeme.
Tento příkaz neudělá žádnou viditelnou změnu. Pouze označí aktuální (poslední) commit jako výchozí bod pro novou větev.
Abychom skutečně přepnuli na novou větev, musíme provést příkaz
git checkout issue/1-hide-traceback
V tuto chvíli nemá přepnutí žádný viditelný efekt – obě větve master a issue/1-hide-traceback odkazují na stejný stav souborů.
Občas vyplavou na povrch detaily z implementace Gitu. V případě větví nejde
obecně vytvořit větve issue
a issue/1
v ten samý okamžik.
Obvykle jsou konvence pro pojmenování větví apod. zdokumentovány v nějaké vývojářské dokumentaci.
Nyní opravte tento problém. Solution.
Commitněte změnu.
Propojení commitů s issue a git commit --amend
Git je při práci s commity poměrně pružný. Pokud zjistíte, že chcete změnit
poslední commit, můžete soubory přidat pomocí git add
a poté zavolat git commit --amend
. Otevře se vám textový editor s již vyplněnou commit
message, kterou můžete změnit.
Nikdy nevolejte --amend
na commit, který jste již odeslali na
server. Tento commit by již mohl být naklonován někým jiným a věci by se
mohly rozbít (ve skutečnosti by bylo možné věci opravit, protože commit by
se v podstatě choval jako větev, ale není to něco, co byste asi chtěli
dělat).
Pokud jste také změnili již odeslaný (pushed) commit, museli byste provést forced push, abyste commit na serveru přepsali. U mnoha projektů to na větvi master není vůbec možné. Proto se raději vyhněte změnám již nahraných commitů.
Použijte tuto funkci a přidejte k poslednímu commitu fixes #1
. Jakmile
tuto verzi odešlete na GitLab, stanou se dvě věci. Zaprvé, issue bude
obsahovat odkaz na commit a na #1
ve zprávě o commitu bude možné kliknout
a otevřít zmíněnou issue.
Protože náš commit tento problém opravil, přidali jsme speciální klíčové slovo
fixes
do zprávy, aby se issue automaticky uzavřela
(existuje spousta
vzorů pro uzavírání issues).
Issue bude uzavřena, jakmile bude commit začleněn do větve master
. To dává
velký smysl: problém může být opraven, ale dokud není kód ve větvi master
,
program stále obsahuje chybu (vzpomeňte si, že ve větvi master
je obvykle
kód, který je dodáván zákazníkovi).
Všimněte si, že to slouží ke dvěma účelům – šetříme čas (nemusíme vůbec přepínat do prohlížeče) a poskytujeme také cenný odkaz na to, který commit byl skutečně zodpovědný za opravu chyby. Všimněte si, že issue na GitLabu zatím není označena jako opravená (vyřešená), protože jsme do zatím na GitLab nic nenahráli.
V projektu byste teď neměly být mít žádné necommitnuté změny.
Přepneme se zpět do větve master
.
Zkontrolujte, zda skript (po přepnutí) neobsahuje vaši opravu.
Hint.
Zkontrolovali jste to? Dobře, můžeme pokračovat.
Všimněte si, že pokud máte skript otevřený v textovém editoru, měl by vás upozornit na změnu souboru na disku. Pokud tomu tak není, načtěte soubor (reload) znovu ručně.
Nahrání (push) nové větve
Přepněte zpět na větev issue/1-hide-traceback
a odešlete ji na GitLab.
Pokud spustíte git push
(jak jste byli zvyklí), bude si Git stěžovat, že
aktuální větev nemá žádnou větev v upstreamu. Znamená to (víceméně), že
tuto větev nahráváte poprvé a Git se chce ujistit, jak má větev na serveru
pojmenovat.
Příjemné je, že Git vám nabídne příkaz, který můžete spustit, abyste zajistili nahrání (push) větve.
git push --set-upstream origin issue/1-hide-traceback
Odkaz, který vám GitLab poslal zpět, prozatím ignorujte.
Znovu otevřete projekt v prohlížeči. Zkontrolujte, zda vaše issue nyní obsahuje odkaz na commit, který ji zmiňuje; a na domovské stránce projektu můžete vybrat, která větev se má zobrazit.
Cvičení
Vyzkoušejte si to sami.
Cvičení I
Nyní vyřešíme druhý problém (když data obsahují neceločíselné hodnoty). Vytvořte novou větev, problém vyřešte a opravu commitněte.
Větev zatím nepushujte.
Několik otázek a věcí k zamyšlení:
- Proč musíte nejprve přepnout na
master
? Jak by vypadalo větvení, kdybyste větvili zissue/1-hide-traceback
? Proč je to špatně? - K vyřešení issue stačí, když prostě řádek přeskočíte (ale upozorněte na něj uživatele!)
- Nezapomeňte do zprávy uvést
closes #2
(nebo nějaký podobný text).
Cvičení II: hot-fix
Předpokládejme, že jste si právě všimli překlepu v souboru README.md
(najděte slovo valeus
).
Tohle chceme opravit rovnou a uděláme to (ale jen pro tentokrát) přímo ve
větvi master
.
Často se tomu říká “hot-fix”: něco, co potřebujete opravit co nejdříve a kde porušení obvyklých zvyklostí týkajících se větvení, revize kódu, testování atd. je spíš na obtíž (i když to opravdu záleží na týmu a produktu, na kterém pracujete).
Přepněte se tedy do větve master
(opravu problému č. 2 jste již
commitnuli, že?), opravte překlepy a commitněte.
Nahrajte vaše změny z hlavní větve.
Graf commitů
V prohlížeči otevřete stránku Repository -> Graph (z projektu). Měly by vám graficky zobrazit vaše větve.
Vedle větve master byste měli vidět novou větev issue/1-hide-traceback
,
která vychází ze stejného commitu.
Grafické zobrazení je dobrým pomocníkem, pokud se ztratíte ve složitém modelu větvení a nejste si jisti, zda by některé změny měly být v konkrétní větvi viditelné, nebo ne.
Účelem není vytvářet složité grafy, i když někdy mohou být docela divoké.
Pro git log
můžete také použít parametr --graph
, abyste získali grafické
zobrazení v terminálu.
Merge requests (žádosti o začlenění)
Žádosti o začlenění (merge requests) jsou pokročilou vychytávkou GitLabu
pro větší týmy.
Ve velkých týmech je code review vyžadován vždy před tím, než je nějaký kód
odeslán do větve master
.
Code review obvykle znamená, že zkušený vývojář si prohlédne váš kód, okomentuje ho a může po vás chtít další úpravy. Představte si pod tím přejmenování funkcí, použití jiných datových struktur nebo opravy dokumentace. Cokoliv od skutečných funkčních chyb po styl zdrojáku.
Merge requesty se hodí přesně na tohle. Než dojde k vlastnímu začlenění (tj. než vaše změny odejdou do hlavní vývojové větve), můžete otevřít tzv. žádost (merge request).
Merge request se hodně podobá issue: ve skutečnosti jsou oba formuláře velmi podobné. To je proto, že Issues popisují známý problém (nebo žádost o novou funkci), zatímco merge requesty popisují, jak byl problém vyřešen. Jak říká GitLab, merge requests are a place to propose changes you’ve made to a project and discuss those changes with others.
Je dobrým zvykem zmínit, které issue daný merge request uzavře (nebo se kterými souvisí).
Opět, pro formátování lze použít Markdown.
Ve velkých týmech budou ostatní vývojáři komentovat váš kód právě během merge requestu a také budou spuštěny automatické testy nad vaším kódem (což se naučíte v některým z dalších cvičení).
Merge requesty mohou dávat smysl i pro osobní projekty: umožní vývojáři rychle zkontrolovat, že je vše v pořádku (třeba, že byly commitnuty všechny soubory apod.).
Pokračování průběžného příkladu
Přepněte se na větev druhé issue a odešlete ji také na GitLab. Budete muset
znovu použít přepínač --set-upstream
.
closes #2
. Pokud
ne, pomůže vám git commit --amend
.
Všimněte si, že po push by se měl zobrazit text informující o možnosti otevřít merge request s odkazem.
Otevřete si tento odkaz v prohlížeči.
Všimněte si, že tzv. merge request (česky asi Žádost o sloučení) ještě nebyl odeslán. Název a popis jsou předvyplněny a vypadají podobně jako formulář, který jsme viděli u issues.
Vytvořte nyní merge request.
Udělejme nyní merge daného merge requestu (je tam na to velké tlačítko).
Zachovejte výchozí nastavení a proveďte merge (tj. ne rebase ani squash).
Po uzavření merge requestu bychom měli vidět nový commit ve větvi master.
Můžete se také znovu podívat na graf commitů a zjistit, jak commity vypadají po merge.
Zkontrolujte nyní issues u svého projektu a všimněte si, že druhá issue by měla být již uzavřena. Můžete také zkontrolovat podrobnosti u issue a všimnout si, jak je commit pěkně propojen s issue.
Zpět v místním klonu repozitáře: nezapomeňte si stáhnout (pull) nejnovější změny z masteru (GitLab vytvořil commit pouze na serveru). Hint.
Mergování z příkazové řádky
Nyní zmergujeme první issue přímo z příkazového řádku, aniž bychom museli otevírat merge request. Protože merge request je vždy vázán na nějakou větev, můžete také vždy mergovat i na příkazovém řádku.
Všimněte si opět dvojího přístupu, který je v Linuxu všudypřítomný: můžete používat pěkné grafické uživatelské rozhraní, ale také plně automatizovatelné rozhraní příkazového řádku.
Nejprve se musíme ujistit, že se nacházíme ve větvi, do které chceme mergovat. Obvykle je to hlavní větev.
Samotný merge je vskutku jednoduchý.
# musíme být na hlavní větvi (git checkout master)
git merge issue/1-hide-traceback
A je hotovo. Znovu odešlete větev master a zkontrolujte graf commitů.
Všimněte si, že merge
je vlastně jen commit, který má jako rodiče dva
různé commity (předchozí verze). Většina voleb jak tak v obou dílčích
příkazech (tj. commit
a merge
) podobná.
Zobrazení seznamu větví a mazání větví
Abychom viděli seznam větví, stačí spustit následující příkaz.
git branch
Někdy je užitečné zobrazit si všechny větve včetně těch na vzdáleném serveru
(vizte též dále) přidáním -a
.
Když je větev zmergovaná, můžeme ji odstranit, abychom udržovali seznam kratší.
git branch -d issue/1-hide-traceback
Odstraněním větve se vlastně je odstraní štítek, který uváděl, že konkrétní
commit patří do určité větve. Proto Git nepožaduje potvrzení při použití
-d
, protože neodstraňujete žádný skutečný kód ani žádné commity. Pokud
však větev ještě není zmergována, Git ji odmítne odstranit (s chybovým
hlášením, že větev není not fully merged, a s nápovědou, abyste použili
velké -D
, pokud ji skutečně chcete smazat).
Začleňování změn z upstreamu (udržování vaší větve aktuální)
Feature branch vám umožní pracovat na nové funkci bez zásahů do hlavní větve. Ale práce v hlavní větvi dál pokračuje a vy potřebujete udržet vaší novou větev aktuální.
To je velmi obvyklá úloha.
Nechcete přijít o důležité aktualizace, které se dějí v master
u.
Často může přeskočení takových aktualizací výrazně zkomplikovat mergování
zpátky.
Podle velikosti a aktivity projektu může dávat smysl mergovat změny z hlavní
větve každý týden nebo dokonce každý den.
Udržování vaší větve aktuální se obvykle označuje jako mergování z upsreamu, protože se tím odkazuje na rodičovský projekt (větev).
Uvidíte, že se to vlastně vůbec neliší od jiného mergování. Je to jen o určení správného směru (tj. změny do hlavní větve nebo změny v hlavní větve do vaší feature větve).
Git vám s tímto procesem vždy pomůže a často to bude zcela automatizovaná záležitost.
Budeme simulovat, že práce v tzv. upstream projektu (tj. v repozitáři, ze kterého jste forknuli) pokračuje, a vy chcete, aby váš repozitář (váš fork) byl aktuální.
V Gitu je toto vše možné a (možná překvapivě) je velmi malý rozdíl mezi tím, zda mergujete svou vlastní (lokální) větev nebo změny někoho jiného, kdo pracuje v úplně jiném forku.
Pro mergování změn z jiného repozitáře, než je ten výchozí (např. jiný projekt na GitLabu), musíme nastavit tzv. remotes.
remote je pojmem, který říká, že váš místní klon ví i o jiných forkách a může vám říct, zda se liší. Opět se jedná o docela zjednodušený pohled na věc, ale je dostačující pro první seznámení s Git remotes. Obvykle očekáváte, že remotes mají společného předka, tj. počáteční commit je ve všech remotech stejný.
Chcete-li zobrazit své remotes, spusťte (v místním klonu svého forku repozitáře s příkladem) následující příkazy
git remote
Pravděpodobně by vypsal pouze origin
. To je výchozí remote: když provedete
git pull
nebo git push
, použije se origin
. Tudíž jste již používali
remotes, i když jste o tom nevěděli ;-).
Spuštění s -v
(pro verbose) vypíše konkrétní adresy URL, na kterých se
nachází vzdálený server. Ve skutečnosti nyní pravděpodobně uvidíte dva
remotes: jeden pro push, druhý pro fetch (pull). Dokonce můžete Git
nakonfigurovat tak, aby stahoval z jiného projektu, než do kterého
nahráváte. Pro nás to však v tuto chvíli není příliš užitečné.
Chcete-li zjistit ještě více podrobností, zkuste git remote show origin
.
Přidání dalšího remote
Přidejme do našeho repozitáře nový remote. Ten bude odkazovat na jiný projekt, abychom mohli porovnat naše změny se změnami v něm (opět zjednodušený pohled na věc).
git remote add upstream gitolite3@linux.ms.mff.cuni.cz:lab07-group-sum-ng.git
Ale počkat. Tohle není repozitář GitLabu! To je ale v pořádku. Přidáme remote, který žije někde jinde. Budou sdílet stejnou historii Gitu a vše bude fungovat.
Výše uvedený příkaz přidal remote s názvem upstream
, který ukazuje na
zadanou adresu. Všimněte si, že příkaz nic nevypsal.
Znovu spusťte git remote
. Co se změnilo?
Všimněte si, že náš repozitář obsahuje příponu -ng
pro novou generaci,
tj. (tak trochu) simulujeme, že původní projekt, ze kterého jste forknuli,
je zastaralý, ale někdo jiný ho převzal a pokračuje ve vývoji jinde.
Práce s remotes
Přidáním remote ještě nedošlo k výměně dat. Gitu musíte říct, aby vše provedl, nic se neděje automaticky. Všimněte si, že pokud se někdy setkáte s jiným verzovacím systémem, bude vám používání systému Git připadat velmi nízkoúrovňové a možná i zdlouhavé. Je to daň za jeho efektivitu a flexibilitu.
Pojďme stáhnout změny z našeho nového remote.
git fetch upstream
Mělo by se zobrazit typické shrnutí jako při klonování/stahování změn v systému Git. Tentokrát odkazuje na data z upstreamového repozitáře.
Ve vaší pracovní kopii (tj. v adresáři s vaším projektem) se však nic nezměnilo. To je v pořádku, žádali jsme pouze o stažení změn, nikoli o jejich uplatnění.
Spusťte však git branch
a git branch --all
, abyste zjistili, ke kterým
větvím máte nyní přístup.
Všimněte si, že přidáním remote nezačne žádná komunikace se vzdáleným
serverem, Git pouze zapíše konfiguraci. Až git fetch
pak skutečně načetl
změny ze vzdáleného serveru. Bez git fetch
bychom neměli žádné informace
o skutečném kódu dostupném na daném vzdáleném serveru.
Porovnávání větví (a jejich mergování)
Nyní prozkoumáme, jak se liší nově přidaný remote.
Začněme zobrazením commitů na remote:
git log remotes/upstream/tests
Jak vidíte, git log
může zobrazit commity pouze v určité větvi (ano,
remotes/...
je ve skutečnosti název větve: koneckonců jste ho viděli v
git branch --all
). A funguje také na souborech (např. git log -- README.md
). Je to vskutku mocný příkaz.
Chtěli jsme se ale podívat, jak se kód liší. To je vlastně ještě důležitější: chcete vidět, jaké změny v kódu byly provedeny a zda bude vůbec možné je mergovat.
git diff remotes/upstream/tests
Měla by se zobrazit záplata, která zobrazí, že nově přidaný remote se liší pouze v jednom: byly přidány automatizované testy.
Vypadají docela dobře – takže je chceme mít i v našem projektu.
Mergněme tedy vzdálenou větev:
git merge remotes/upstream/tests
Protože nedochází ke konfliktům (tj. obě větve – master
a
remotes/upstream/tests
– změnily různé soubory), mergování by mělo být
automaticky dokončeno.
Zkontrolujte adresář projektu: je v něm soubor tests.bats
?
Všimněte si, že (commit) zprávu o mergování můžete změnit pomocí --amend
.
Řešení konfliktů
Stejným způsobem se připravte na mergování (tj. ještě nespouštějte git merge
) s upstream/hotfix
.
Jak jste si pravděpodobně všimli, druhá větev obsahuje opravu překlepu. Ale to už jste opravili (pokud ne, opravte to před mergováním!).
Merge povede k takzvanému konfliktu: dva vývojáři upravili stejný souboru a provedli své individuální úpravy. To musíme vyřešit ručně.
To je zcela běžné a není třeba se toho bát. Git vám dokáže hodně pomoci – pokud dojde ke změnám v různých částech souboru, dokáže je bez problémů sloučit. Když ale obě větve změní stejné řádky, je na vás, abyste to vyřešili. To je zcela přirozené a byli byste překvapeni, kolikrát je Git schopen sloučit věci automaticky.
Dost bylo teorie, nyní spusťte příkaz merge
:
git merge remotes/upstream/hotfix
Toto mergování skončí chybou a Git vás bude informovat o konfliktu.
Zkontrolujte výstup příkazu merge
. Všimněte si, jak se vám Git snaží
poradit, co lze udělat…
Spusťte také git status
a prozkoumejte jeho výstup.
Nyní přichází složitější část celého postupu: je třeba vyřešit konflikt.
V našem případě je to poměrně jednoduché. U složitého softwaru může být řešení konfliktu velmi složitou operací, protože je třeba nejprve zkontrolovat několik míst a změny mentálně zkombinovat. Mít automatizované testy může pomoci, ale analytické myšlení je určitě výhodou.
Jakmile konflikt vyřešíte, musíte zavolat git add
(jako při normálním
commitu - mergování je koneckonců stále jen commit), abyste konflikt
označili jako vyřešený (resolved).
git add README.md
Chcete-li mergování dokončit, spusťte příkaz git commit
jako při běžném
commitu.
Nezapomeňte změny nahrát na server.
Jak by nyní vypadalo grafické znázornění commitů v GitLabu?
Před otevřením stránky Graphs v GitLabu si ji zkuste načrtnout na papír.
I když je systém Git často schopen provést mergování sám, tak za to, že výsledek dává smysl, vždy odpovídá uživatel.
Je snadné si představit situaci, kdy dva vývojáři změní různé části programu (aniž by cokoli rozbili), ale kombinovaná změna nebude fungovat.
Dobré testy v těchto situacích určitě pomůžou.
Zcela nesouvisející témata :-)
Následující příklady berte jako exkurzi, že skripty nejsou jen o nudných textových souborech, ale že jejich možnosti jsou nekonečné.
Úlohy před cvičením (deadline: začátek vašeho cvičení, týden 27. března - 31. března)
Následující úlohy musí být vyřešeny a odevzdány před příchodem na vaše cvičení. Pokud máte cvičení ve středu v 10.40, soubory musí být nahrány do vašeho projektu (repozitáře) na GitLabu nejpozději ve středu v 10.39.
Pro virtuální cvičení je deadline úterý 9:00 (každý týden, vždy ráno, bez ohledu na možné státní svátky apod.).
Všechny úlohy (pokud není explicitně uvedeno jinak) musí být odevzdány přes váš repozitář na úkoly. Pro většinu úloh existují automatické testy, které vám mohou pomoci zkontrolovat úplnost vašeho řešení (zde je popsáno jak číst jejich výsledky).
Některé úlohy jsou nahrány do jiné větve než je master
.
Testy se to snaží kontrolovat, ale ne vždy je to možné a proto některé na
větvi master
selžou i v případě, že je všechno v pořádku.
07/avg.py
(60 bodů, skupina git
)
Zkopírujte následující kód do souboru 07/avg.py
ve vašem projektu do
větve master.
#!/usr/bin/env python3
import sys
def main():
values = list(map(int, sys.argv[1:]))
avg = sum(values) / len(values)
print(avg)
if __name__ == "__main__":
main()
Skript vypočítá průměr čísel zadaných na příkazovém řádku, např. při
spuštění ./avg.py 1 2 6
vypíše 3,0
.
Vytvořte větev v Gitu s názvem lab-07/avg
, kde opravíte kód tak, aby
fungoval i v případě, že nejsou zadány žádné argumenty (program v takovém
případě vypíše 0
).
Váš repozitář musí obsahovat alespoň dva commity tohoto souboru: jeden
importující aktuální řešení a jeden (ve větvi lab-07/avg
) opravující
problém.
Automatizované testy také kontrolují, zda jsou spuštěny na správné větvi.
Nezapomeňte nahrát lab-07/avg
do Gitlabu a zkontrolovat výstup testu.
07/issue.txt
(40 bodů, skupina git
)
Vytvořte Issue s názvem 07/issue
ve svém projektu, která představuje
tento úkol.
Uzavřete tuto issue z commitu, který přidává text ‘SOLVED’ do souboru
07/issue.txt
.
Oprava může být provedena v jakékoli větvi, ale nakonec musí být zamergována
do větve master
, aby byla issue skutečně opravena.
Automatické testy nemají přístup k vašemu seznamu Issues.
Ujistěte se, že jste odkázali na správnou issue, my to pak zkontrolujeme při spuštění testů mimo Gitlab.
Úlohy po cvičení (deadline: 16. dubna)
Očekáváme, že následující úlohy vyřešíte po cvičení, tj. poté, co budete mít zpětnou vazbu k vašim řešením úloh před cvičením.
Všechny úlohy (pokud není explicitně uvedeno jinak) musí být odevzdány přes váš repozitář na úkoly. Pro většinu úloh existují automatické testy, které vám mohou pomoci zkontrolovat úplnost vašeho řešení (zde je popsáno jak číst jejich výsledky).
07/UPSTREAM.md
(30 bodů, skupina git
)
Možná jste si všimli, že repozitář s úlohami byl ve skutečnosti forkem jiného. (To bylo z technických důvodů, protože to zjednodušuje vytváření projektů.)
Ale také to znamená, že můžete mergovat změny od nás.
Rodičovský projekt teď obsahuje soubor 07/UPSTREAM.md
s nezajímavým
obsahem.
Přimergujte tento soubor do vašeho repozitáře. Nedělejte rebase ani squash, udělejte, prosím, normální merge.
Testy mohou po určité době začít selhávat (GitLab klonuje pouze nedávnou historii).
To je v pořádku: důležité je, že test v určitém okamžiku proběhl v pořádku.
07/group_sum.py
(70 bodů, skupina git
)
V tomto úkolu znovu projdete přípravu na cvičení, jen tentokrát ve vašem repozitáři s úlohami.
Nad souborem group_sum.py
z repozitáře s příklady proveďte následující.
Import (1)
Naimportujte skript a vytvořte commit s původní verzí ve větvi master.
Tato verze bude obsahovat všechny problémy, které jsme zmínili během cvičení.
Issue (2)
Vytvořte dva issue pro dvě velké chyby v programu.
Jednu issue pro nevypisování pěkné chybové zprávy, když soubor nelze otevřít.
A druhou pro přeskočení řádku s neplatnými údaji.
Větve (3)
Počínaje commitem z bodu (1) vytvořte v repozitáři s úlohami dvě větve navázané na vaše issues.
Pojmenujte větve jako issue/N-popis
, kde N
musí odkazovat na dříve
vytvořené issues (2).
Oprava problému (4)
Opravte každý problém z bodu (2) ve větvích vytvořených v bodě (3).
Issue uzavřete prostřednictvím commit zpráv.
Obě větve nahrajte na GitLab, abychom je našli i tam.
Mergování oprav
Větve vytvořené v bodech (3) a (4) zamergujte do větve master (tj. vytvoříte dva merge commity) a odešlete je do Gitlabu.
Pokud chcete, můžete také vytvořit merge request. V takovém případě neodstraňujte původní větve!
Učební výstupy
Učební výstupy podávají zhuštěný souhrn základních konceptů a dovedností, které byste měli umět vysvětlit a/nebo použít po každém cvičení. Také obsahují absolutní minimum, které je potřebné pro pochopení navazujících cvičení (a dalších předmětů).
Znalosti konceptů
Znalost konceptů znamená, že rozumíte významu a kontextu daného tématu a jste schopni témata zasadit do většího rámce. Takže, jste schopni …
-
vysvětlit rozdíl mezi forkem projektu a klonem (pracovní kopií) repozitáře
-
vysvětlit, co je větev v Gitu
-
vysvětlit, co je feature branch
-
vysvětlit, co je mergování větví v Gitu
-
vysvětlit, co je to merge (pull) request a kdy je užitečný
-
vysvětlit, co je to Git remote
-
vysvětlit, kdy může dojít ke konfliktu při slučování (merge) v Gitu a jak jej lze vyřešit
-
vysvětlit, co se obvykle míní tzv. upstream repozitářem (projektem)
Praktické dovednosti
Praktické dovednosti se obvykle týkají použití daných programů pro vyřešení různých úloh. Takže, dokážete …
-
vytvořit větev v Gitu lokálně pomocí příkazu
git branch
-
nahrát novou větev v Gitu na vzdálený server
-
vytvořit merge request (žádost o začlenění) z feature větve v GitLabu
-
přepínat mezi větvemi (
git checkout
) -
sloučit (merge) lokální větve Gitu pomocí
git merge
-
řešit konflikty při mergování
-
nastavit Git remotes
-
používat aliasy Gitu pro efektivnější práci
-
volitelné: používání prográmku
youtube-dl
-
volitelné: používání VLC z příkazové řádky
Seznam změn na této stránce
-
2023-03-25: Přidány úlohy po cvičení.
-
2023-03-27: Vysvětlení fast-forward u hodnocení úlohy po cvičení.
-
2023-03-27: Varování ohledně pojmenování větví.