Úvod do gitu

Semestrální práce budete v tomto předmětu odevzdávat prostřednictvím gitu. Protože předpokládáme, že ne všichni z vás git znají, přinášíme vám k němu malý úvod.

Instalace

Pokud používáte nějakou distribuci Linuxu, git nainstalujete klasicky přes balíčkovací systém. Pro ostatní systémy je možné ho stáhnout přímo z oficiálních stránek. Základní grafické nástroje git gui a gitk jsou zahrnuty, v některých distribucích jsou v samostatných balíčcích (v Debianu git-gui a gitk).

TL;DR

Nejzákladnější základy

Git patří mezi verzovací systémy. To znamená, že vám umožňuje udržovat si verze něčeho – my budeme mluvit o programu, ale může jít o cokoliv, třeba několik zdrojových kódů, jeden soubor s poznámkami z analýzy, nebo klidně celou bakalářku tvořenou programy, daty, textem práce, obrázky, poznámkami, …

Mezi zásadní výhody gitu patří jeho flexibilita, takže s gitem dokážete v podstatě cokoliv – samozřejmě ale komplikované problémy mívají komplikované řešení. My zůstaneme u těch jednoduchých, takže by komplexita měla zůstat v únosné míře. Tento úvod je zjednodušený, a místy v zájmu srozumitelnosti trochu nepřesný, ovšem na základní použití by měl posloužit velmi dobře.

Pojmem, kterému se v povídání o gitu nemůžeme vyhnout, je repozitář. V prvním přiblížení si ho představíme jako složku obsahující náš program. Tato složka může obsahovat libovolné množství souborů a složek (které mohou obsahovat další soubory a složky, a tak dále). Repozitář se nějak jmenuje, třeba semestralka.git. Jak to se jmény bývá, je vhodné, aby jméno repozitáře přímočaře souviselo s jeho obsahem, ale technicky to nutné není.

Verzí programu budeme označovat přesný stav složky (repozitáře). To zejména znamená, které soubory v ní jsou a jaký přesně mají obsah (ale také třeba jaká mají práva). Dvě verze se od sebe mohou lišit třeba opravou středníku v jednom souboru .cpp, přidáním několika testů do souborů s testy, odstraněním zastaralé (deprecated) funkce, … Opět, technicky může verze vypadat jakkoliv. Prakticky je vhodné, aby každá verze programu byla zkompilovatelná a přidávala či ubírala nějakou dobře definovanou část funkcionality programu. O verzích budeme později mluvit jako o commitech.

Založení repozitáře

Repozitář můžeme založit přímo na gitlabu intuitivně tlačítkem “New project”. Potom už si jen musíme nový repozitář naklonovat na svůj počítač (viz dále). Gitlab nám dokonce dá po založení návod, jak to udělat.

Protože git je distribuovaný verzovací systém (to znamená, že každý klon je plnohodnotným repozitářem), můžeme si repozitář vytvořit klidně i jenom lokálně pomocí příkazu git init. Pak ale samozřejmě nemáme jak změny publikovat1).

Naklonování repozitáře

K vlastní práci v repozitáři si musíme pořídit jeho klon. Existující repozitář si na svůj stroj naklonujeme pomocí příkazu git clone, tedy např. git clone git@gitlab.fel.cvut.cz:uzivatel/semestralka.git. Ale počkat … jak se autentizovat? Pro přístup do repozitářů gitlabu si musíte vytvořit SSH klíč (pokud ještě nemáte) a přidat jeho veřejnou část do Gitlabu na svůj profil. Může to znít složitě, ale ve skutečnosti je to jen pár příkazů a na stránkách gitlabu je podrobný návod, jak na to. Po naklonování repozitáře na disku uvidíme nejnovější verzi programu.

Synchronizace se serverem

O repozitáři jsme v prvním přiblížení mluvili jako o složce. Je to ale trochu víc – kromě samotné složky, resp. jejího obsahu, je repozitář tvořený také určitými nastaveními, a zejména seznamem všech verzí programu.2) Právě seznam verzí je důvod, proč se budeme chtít seznámit s příkazy git pull a git push. Pokud zavoláme git pull, překopírují se nám na disk všechny verze, které existují na serveru3), a neexistují u nás. Naopak, zavolání git push způsobí, že se všechny verze, které existují u nás a neexistují na serveru, překopírují na server. Zde předpokládáme, že s repozitářem pracujete jako jediní a pouze na jednom stroji. Pokud např. na svém stolním počítači zavoláte git pull, vyrobíte nové verze, zavoláte git push a následně na svém notebooku zavoláte git pull, bude vše stále fungovat. Pokud ale vyrobíte nové verze jak na stolním počítači, tak na notebooku, příkazy se začnou chovat zvláštně a budou si stěžovat. Můžete zkusit git pull --rebase, v horším případě budete muset googlit git merge (nebo se zeptat na fóru).

Vytváření commitů (verzí)

Už jsme si řekli, jak dostat nové verze ze serveru k nám a naopak, ale ještě jsme nemluvili o tom, jak nové verze vyrobit. To proto, že vyrábění nových verzí je maličko trikové. Git odlišuje tři věci: zaverzované (commitnuté) podoby souborů, podoby připravené k zaverzování (ke commitu) a soubory (resp. podoby souborů), o kterých vlastně neví. Pokud v repozitáři změníte soubor nebo vytvoříte nový, git to ignoruje. Je potřeba mu říct, aby si nového souboru, resp. změny obsahu v souboru všiml. K tomu slouží příkaz git add. Předávají se mu všechny soubory, u kterých si má git všimnout změny (přičemž změnou může být i jejich vytvoření). Voláte tedy např. git add reversi.h reversi.cpp. Tím se změny v daných souborech připraví ke commitu. (Obvykle se připraveno ke commitu označuje jako staged.) K vytvoření nového commitu pak slouží příkaz git commit. Do vytvářeného commitu přidá git všechno, co je k němu připraveno (tedy na co bylo dříve zavoláno git add). Součástí vytvářeného commitu je také jeho popis, resp. zpráva o změně (commit message). Po zavolání git commit se vám otevře textový editor, kam tuto zprávu zadáte, a teprve uložením a uzavřením editoru se vytváření nového commitu dokončí. Pokud byste zadali prázdnou zprávu, vytváření nového commitu se přeruší. Pozor si dejte zejména na posloupnost editace souboru, git add soubor, další editace, git commit, kdy se do nového commitu promítnou pouze změny z první editace.

Do svého repertoáru příkazů pro git byste určitě měli zařadit git status. Tento příkaz vám, jak název napovídá, vypíše stav repozitáře. Přesněji řečeno, vypíše vám (na anglicky mluvícím systému):

  • řádek On branch master – ten směle ignorujte, byl by důležitý, kdybyste pracovali s větvemi,
  • jak jste na tom vůči serveru s množstvím verzí; běžně asi uvidíte něco jako Your branch is ahead of 'origin/master' by N commits, což znamená, že u vás existuje N verzí, které neexistují na serveru
  • sekci souborů, které jsou připraveny k zaverzování (obsahují změny a zavolali jste na nich git add)
  • sekci souborů, které obsahují změny, ale git o změnách neví (od poslední změny se na nich git add nevolalo)
  • sekci souborů, o kterých git vůbec nic neví (od jejich vytvoření se na nich nezavolalo git add)

Pokud by kterákoliv ze zmíněných sekcí neobsahovala žádný soubor, git ji vůbec nevypíše.

Commitování z GUI

Commitování souborů z příkazové řádky může být někdy trochu nešikovné, obzvlášť, pokud máme změn hodně, chceme commitnout jen některé nebo se chceme při psaní zprávy dívat, co jsme udělali za změny, aby byl obsah zprávy hezky popisný. V tom případě se může hodit utilitka git gui, která nám zobrazí:

  • seznam změněných a neverzovaných souborů
  • seznam souborů připravených ke commitu
  • okénko pro zprávu commitu a tlačítko “Commit”
  • prostor pro zobrazení změn v souboru (výstup git diff)

Grafické rozhraní sice vypadá jak z minulého tisíciletí, ale je velmi jednoduché a mocné. Utilita je součástí gitu (i když v některých linuxových distribucích je v samostatném balíčku git-gui).

Po kliknutí na jméno souboru se nám zobrazí změny v příslušném souboru, po kliknutí na jeho ikonku se buď připraví ke commitu (jako po zavolání git add), nebo se naopak označí, jako že ho commitovat nechceme (pokud byl před kliknutím v souborech ke commitu).

Ignorování některých souborů

Když si svůj projekt zkompilujeme, vygeneruje se spoustu souborů, které se nám začnou objevovat ve výpisu git status. Ty ale nikdy verzovat nechceme. Hodilo by se tedy gitu nějak říct, že má dané soubory ignorovat. Toho dosáhneme tak, že vytvoříme soubor .gitignore a do něj napíšeme seznam souborů (nebo patternů), které ignorovat:

# ignoruj objektové soubory
*.o
# anebo rovnou celý adresář build
build

Soubor .gitignore se může vyskytovat i v jakékoliv podsložce – pak se ale bude vztahovat jen na soubory (a adresáře) v ní.

Zobrazení historie

Užitečným příkazem může být také git log. Ten vypíše seznam commitů, pro každý z nich vypíše kód commitu, autora, datum vytvoření a popis (commit message). Pokud by vám vrtalo hlavou, kde se vzal kód commitu, je to SHA hash kompletního obsahu repozitáře v daném commitu.

Opět můžeme využít standardní grafický nástroj gitk (v Debianu samostatný balíček gitk). Ani ten nás neoslní moderním designem, ale zato nás oslní svou praktičností. K vidění je v něm:

  • Seznam commitů, pro každý z nich pak první řádek commit message, autora a datum. Pokud bychom používali větve, viděli bychom zde i znázorněné větvení.
  • Celou zprávu a změny aktuálně vybraného commitu, spolu se seznamem změněných souborů.

Kontextové menu na na commitu v seznamu commitů opět umožňuje dělat kouzla, např. vytvářet značky (tagy).

Zobrazení změn (diff)

V neposlední řadě se pak hodí příkaz git diff. Ten vám ukáže odlišnosti. V základním použití (tedy přímo git diff) vám ukáže, jak se soubory na disku liší od své podoby v nejnovějším commitu. Pozor, toto volání vám neukáže nově přidané soubory. Spousta vývojářů běžně používá git diff --cached, to vám ukáže vše, co je připraveno ke commitu (tedy vše, co se přidá do nového commitu, pokud zavoláte git commit). V některých případech se vám může hodit přidat k volání diffu --word-diff=color, v takovém případě nebudou ve výpisu zvýrazněné celé řádky, ale přímo ty jejich části, které se liší. A zmíníme i git diff <kód commitu> <kód commitu>, který vám ukáže odlišnosti mezi commity identifikovanými svými kódy. K této identifikaci ještě dvě poznámky:

  1. Kódy není nutné psát celé, stačí libovolný unikátní prefix.
  2. Chcete-li se odkázat na nejnovější commit, můžete místo jeho kódu použít alias HEAD.

Tagy

Říkali jsme, že každý commit reprezentuje určitou verzi projektu. Tím jsme měli na mysli pracovní verzi. V určitou chvíli ale budeme se stavem našeho projektu spokojení, prohlásíme aktuální verzi za konečnou (tedy, konečnou do doby nalezení prvního bugu) a budeme ji chtít nějak pojmenovat – ať už se jedná o nějaký open-source program (a chceme udělat release verze X.Y, tedy např. v0.1), nebo o semestrálku (chceme ji odevzdat, tedy např. odevzdani-1). Toho dosáhneme tak, že daný commit označíme tzv. tagem (česky štítkem). V historii pak budeme mít jasně označené, který stav (commit) odpovídá které release verzi.

Tag se dá vytvořit příkazem git tag, např. git tag -a v0.1, anebo z kontextového menu v programu gitk, při kliknutí na patřičný commit (viz Zobrazení změn). Samotný git tag pak vypíše seznam všech tagů.

Seznam všech tagů se nám taky zobrazí na gitlabu v záložce Repository → Tags. A jako bonus můžeme všude místo SHA hashe commitu psát název jeho tagu.

Další literatura

Pokud chcete Gitu porozumět trochu víc, doporučujeme již zmiňovanou knihu Pro Git, dostupnou online v češtině i v angličtině.

Vhod taky přijde tahák se základními příkazy a v neposlední řadě taky Visual cheatsheet.

Automatické testování s použitím Gitlab CI

Doplníme.

1)
Museli bychom přidat tzv. remote repozitář pomocí příkazu git remote add. git clone to udělá automaticky.
2)
Technicky je přirovnání ke složce zcela v pořádku. V každém gitím repozitáři existuje složka .git, která tato nastavení a verze obsahuje.
3)
Na serveru, nebo kdekoliv jinde – myslíme tím obecně místo, kde byl repozitář vyrobený a odkud jste si ho naklonovali.
courses/b6b36pcc/ostatni/git-intro.txt · Last modified: 2018/12/04 16:13 by jerabma7