Cvičení: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.
- Předstartovní kontrola
- 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í) a práce s remotes
- Konflikty při merge (a jak je řešit)
- Shrnutí větvení
- Zcela nesouvisející témata :-)
- Úlohy k ověření vašich znalostí
- 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í.
Předstartovní kontrola
- Znáte základní Gitové příkazy zpaměti (
clone
,pull
,push
,log
,status
,diff
,add
,commit
). - Nahráli jste váš veřejný klíč do jednoho ze souborů
05/key.[0-9].pub
. - Jste odpočinutí a čerství: tohle je asi nejužitečnější cvičení z celého předmětu: nemůžete se stát vývojáři, aniž byste tohle všechno znali :-)
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/2024/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
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í.
git pull
(nebo git push
), je pravděpodobné,
že Git/GitLab již vytvořil nějaké větve a merge za vás. Nyní to uděláme
záměrně :-).
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.
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.
Podle projektu se můžete setkat i s větvemi jako development
, kde
mergování nevyžaduje code review, nebo s větví production
, jež označuje
kód, který bude distribuován (často automaticky) zákazníkům.
Doporučujeme přečíst A Simple Git Branch Workflow (dev.to), pokud chcete vědět více detailů o tom, jak tento přístup funguje.
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, když soubor neexistuje. 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-file-not-found
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-file-not-found
V tuto chvíli nemá přepnutí žádný viditelný efekt – obě větve master a issue/1-hide-traceback-file-not-found odkazují na stejný stav souborů.
Místo toho si také můžete zapamatovat jediný příkaz, který vytvoří větev a přepne na ni.
git checkout -b issue/1-hide-traceback-file-not-found
git switch
, který pravděpodobně časem nahradí
git checkout
. Zatím je ale označen jako experimentální a proto ho tady
nepoužíváme.
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. Řešení.
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ů.
git commit --amend
vytvoří nový commit místo
původního. To má několik drobných následků, z nichž nejdůležitější je, že
historie před a po změně jsou z pohledu Gitu odlišné. To znamená, že pokud
jste již odeslali původní commit, neměli byste jej měnit, protože bude
obtížné odeslat ten nový (protože nerozšiřuje historii na serveru).
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.
Nápověda.
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ě.
Poznámka ke git add --patch
(nebo git add -p
)
Někdy se můžete setkat se situací, kdy v jednom souboru změníte dvě věci, které spolu nesouvisejí. Například, když opravíte funkční chybu, ale zároveň si všimnete překlepu v komentáři. V takové situaci byste změnu měli rozdělit do dvou commitů.
Pokud jsou změny ve dvou různých souborech, je to snadné: jednoduše zavoláte
git add
na první soubor, git commit
a pak git add
na druhý soubor.
Pokud jsou změny ve stejném souboru, je možné použít git add -p
(pro
--patch
), kdy Git interaktivně zobrazí každý hunk – v podstatě jednu
změnu – a zeptá se, zda má být git add
-ován, nebo ne.
Pomocí git add -p
můžete snadno rozdělit své commity a také si
zkontrolovat, co jste udělali, aniž byste museli v editoru provádět nějaké
šílené un-do/re-do.
Všimněte si však, že možnosti systému Git jsou omezené, pokud jde o
posuzování toho, co je změna. Někdy, když jsou změny blízko sebe (tj. na
stejném řádku), Git je nebude považovat za dva různé hunky. Budete nuceni
ručně upravit hunk (e
) podle pokynů poskytovaných systémem Git.
Nahrání (push) nové větve
Přepněte zpět na větev issue/1-hide-traceback-file-not-found
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-file-not-found
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.
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-file-not-found
, 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). Nápověda.
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.
Také se ujistěte, že je vaše hlavní větev aktuální (v našem příkladu se ujistěte, že jste stáhli změny přimergované ve webovém rozhraní GitLab).
Samotný merge je vskutku jednoduchý.
# musíme být na hlavní větvi (git checkout master)
git merge issue/1-hide-traceback-file-not-found
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-file-not-found
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í) a práce s remotes
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řed pokračováním se ujistěte, že váš veřejný klíč funguje pro naše
repozitáře na adrese gitolite3@linux.ms.mff.cuni.cz:lab05-LOGIN
(podrobnosti u cvičení 05).
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.
master
.
Začněme zobrazením commitů na remote:
git log remotes/upstream/topic/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.
git log README.md
: dokud je Git schopen
rozlišovat mezi názvy souborů a větví. Protože se názvy souborů obvykle
liší od názvů větví, bude to ve většině případů fungovat i bez explicitního
oddělovače --
.
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/topic/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 (topic/tests
):
git merge remotes/upstream/topic/tests
Protože nedochází ke konfliktům (tj. obě větve – master
a
remotes/upstream/topic/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
.
Konflikty při merge (a jak je řešit)
Stejným způsobem se připravte na mergování (tj. ještě nespouštějte git merge
) s upstream/hotfix/readme-typo
.
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/readme-typo
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.
Jakmile konflikt vyřešíte (tj. změníte zdrojáky), 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.
Shrnutí větvení
Výše uvedená témata představují přibližně 90 % toho, co budete vůbec kdy potřebovat vědět o větvích pro každodenní vývoj.
Nezabývali jsme se pokročilými tématy, jako je přepisování historie, rebasování atd. Vždy si je můžete najít v Git knize.
Zbytek cvičení je věnován některým dalším rozšiřujícím tématům, která ale můžete klidně přeskočit :-).
Konec cvičení obsahuje další příklad, na kterém si můžete vyzkoušet větvení zcela sami.
Zkontrolujte si všemu rozumíte
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é.
VLC
VLC je populární multimediální přehrávač dostupný pro mnoho platforem. Nebudeme vás nudit grafickým uživatelským rozhraním, ale místo toho si ukážeme několik zajímavých možností příkazového řádku. Mohou se hodit pro specifické případy, jako je třeba kioskový režim (např. na výstavě).
Následující přepínače příkazového řádku přehrají zadané video, ale rozdělí ho do čtyř různých oken. Možná užitečné, pokud máte více monitorů s velmi tenkými okraji.
vlc --video-splitter wall --wall-cols 2 --wall-rows 2 --wall-element-aspect 4:3 video.mpg
VLC lze použít také ke streamování videa po síti. Za předpokladu, že máte v
aktuálním adresáři soubory 1.mp4
, 2.mp4
a 3.mp4
, připravte následující
soubor (pojmenujte jej vod.vlc
):
new channel1 vod
setup channel1 input 1.mp4
setup channel1 enabled
new channel2 vod
setup channel2 input 2.mp4
setup channel2 enabled
new channel3 vod
setup channel3 input 3.mp4
setup channel3 enabled
V každém bloku je nastavena jedna konfigurace videa on-demand (tj. klient požádá o konkrétní video a server VLC ho poskytne).
Dále spustíme VLC v příkazovém řádku v režimu serveru, aby naslouchal připojení RTSP na portu 5554.
cvlc --vlm-conf vod.vlc --rtsp-tcp --rtsp-port 5554
Vybrané video nyní můžeme přehrát následujícím příkazem.
vlc rtsp://127.0.0.1:5554/channel3
Výše uvedené předpokládá, že video přehráváte na stejném počítači. První
příkaz lze rozšířit pomocí --rtsp-host
, aby mohl poslouchat na jiném
rozhraní a streamovat video po síti (a druhý příkaz spustit na jiném
počítači).
youtube-dl
youtube-dl je nástroj pro stahování videí, který dokáže vyhledávat a stahovat videa z různých webových stránek. Jako nástroj příkazového řádku jej lze použít ve skriptech nebo ke stahování videí pro pozdější prohlížení (tj. stahování s rychlým připojením a pozdější přehrání).
Jednou z podporovaných stránek je
OpenClassroom
Standfordské univerzity. Zde jsou některá
videa ve formátu FLV, ale youtube-dl
dokáže video převést jednoduchým
přidáním --recode-video mp4
:
youtube-dl --recode-video mp4 "http://openclassroom.stanford.edu/MainFolder/VideoPage.php?course=IntroToAlgorithms&video=CS161L1P1&speed=100"
youtube-dl
podporuje mnoho dalších webů: stahování z mnoha z nich je
výslovně zakázáno jejich podmínkami používání (pro mnohé je použití
podobných nástrojů na hranici tzv. fair use policy).
ffmpeg
Dalším zajímavým nástrojem je ffmpeg
, který je obecným konvertorem
videoformátů. Kromě triviální konverze mezi různými formáty umí i spoustu
dalších efektů.
Jako obvykle: výhoda rozhraní příkazového řádku je podstatná pro hromadné konverze, kde není nutná interakce uživatele.
Následující příkaz například převede zvuk na AAC, přičemž video zůstane zachováno bez jakýchkoli úprav. Používali jsme ho pro videa ze cvičení (během vzdálené výuky), aby fungovaly i ve Firefoxu.
ffmpeg -i "input_file.mp4" -c:v copy -c:a aac "output_file.mp4"
Dokáže toho však mnohem víc. Nejprve si stáhneme následující klipy a uložme
je jako 1.mp4
, 2.mp4
a 3.mp4
.
https://www.videvo.net/video/airport-departure-board/6001/
https://www.videvo.net/video/swiss-aircraft-taking-off/4061/
https://www.videvo.net/video/airplane-window-view/5176/
Následující příkaz pak vloží tyto klipy vedle sebe do jednoho videa.
Používá více -i
k načtení více vstupních souborů a pak pomocí složitého
filtru poskládá videa vedle sebe. Příkaz -t
se používá k omezení převodu
pouze na prvních 10 sekund.
Proměnné se používají pouze k uložení informací o dané pipeline. V příkazu
f_rescale
změníme měřítko všech videí. Proměnná [0]
označuje první
vstupní soubor (první v poli vstupních souborů), [v0]
je uživatelský
identifikátor pro pojmenování výsledku filtru. V f_stack
použijeme filtr
xstack
s danou specifikací rozvržení – pokud vás zajímají podrobnosti o
polohování pomocí 0_0|w0_0|w0_h1
, podívejte se na tuto
stránku.
f_rescale='[0]scale=-1:360[v0];[1]scale=-1:180[v1];[2]scale=-1:180[v2]'
f_stack='[v0][v1][v2]xstack=inputs=3:layout=0_0|w0_0|w0_h1[v]'
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -filter_complex "$f_rescale;$f_stack" -map "[v]" -t 10 -vsync 2 output.mp4
Pokud potřebujete výše uvedené provést pro jedno video, bude jistě
jednodušší použít interaktivní editor. Pokud však potřebujete zpracovat
více videí se stejnou nebo podobnou konfigurací, může být lepší volbou
ffmpeg
.
Úlohy k ověření vašich znalostí
Očekáváme, že následující úlohy vyřešíte ještě před příchodem na cvičení, takže se budeme moci o vašich řešeních na cvičení pobavit.
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
-
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
-
2024-04-04: Poznámka o zvláštních chybách v GitLabu.
-
2024-04-18: Upřesnění řešení konfliktů.