Seriál Online kurz Git – Lokálna Práca so Súbormi – 2. diel

Toto je pokračovanie seriálu o verzionovacom (verzovacom) systéme Git, ktorého 1. diel si môžeš pozrieť tu (Seriál Git – Začíname s Gitom – 1. diel). V ňom som vysvetlil to, čo to Git je a aké má výhody ho používať. Tiež som ukázal jednoduchý príklad pridania súboru do repozitára. Takto vyzbrojení základnými poznatkami sa môžeme pustiť do širšej práce so súbormi. Git je nepostrádateľný nástroj pre vývojárov, ktorý umožňuje efektívnu správu verzií kódu. Práca so súbormi v lokálnom prostredí je jednou z kľúčových oblastí, kde Git exceluje. V tomto článku sa pozrieme na rôzne aspekty práce so súbormi lokálne v Gite, vrátane pridávania, úprav, odstraňovania súborov a riešenia konfliktov.

Začiatok s Git

Ak ešte nemáte Git nainštalovaný, môžete si ho stiahnuť a nainštalovať z oficiálnej stránky. Po inštalácii si nastavte svoje meno a e-mail, ktoré budú používané pri commitovaní zmien.

Nastavenie mena a e-mailu:

git config –global user.name „Vaše Meno“
git config –global user.email „vas.email@example.com“

Vytvorenie nového Git repozitára:

mkdir moj-projekt
cd moj-projekt
git init

Pridávanie a commitovanie súborov

Pridávanie súborov do Git repozitára je jednoduché. Stačí vytvoriť alebo upraviť súbory a potom ich pridať do staging area pomocou príkazu git add. Následne môžete zmeny commitovať do histórie projektu.

Príklady:

echo „print(‚Hello, world!‘)“ > hello.py # Vytvorenie nového súboru
git add hello.py # Pridanie súboru do staging area
git commit -m „Pridanie hello.py s jednoduchým programom“ # Commitovanie zmien
Úprava a commitovanie zmien

Keď upravíte existujúce súbory, je dôležité pravidelne commitovať zmeny, aby ste mali prehľadnú históriu projektu.

Príklady:

echo „print(‚Hello, Git!‘)“ >> hello.py # Úprava existujúceho súboru
git add hello.py # Pridanie zmien do staging area
git commit -m „Uprava hello.py s novým výstupom“ # Commitovanie zmien

Git príkazy alebo než sa začnú sypať ďalšie príkazy

Ešte predtým než sa ponoríme do sveta príkazov je dobré si o nich niečo povedať:

  1. porcelán vs. potrubia – nie, neodbočil som náhle do vodoinštalačnej oblasti. Toto je naozaj stále o Gite (a humore jeho tvorcov). Git rozlišuje 2 typy príkazov: nízkoúrovňové príkazypotrubia alias plumbing a vysokoúrovňové porcelánové príkazy alias porcelain (budem používať anglický výraz, pretože sa s prekladom akosi neviem stotožniť). Plumbing príkazy sú podrobnejšie príkazy, ktoré vedia detailnejšie manipulovať s repozitárom. Naproti tomu porcelain príkazyjednoduchšie na použitie, pretože čiastočne zakrývajú komplexnosť Gitu. Príkaz commit, ktorý sme použili v predchádzajúcom dieli, je porcelain príkaz podobne ako väčšina, s ktorými budeme teraz pracovať. Je veľmi pravdepodobné, že ak s Gitom začínaš, tak sa k plumbing príkazom spočiatku ani nedostaneš. A prečo takéto názvy? Je to prirovnanie k tomu, čo obsahuje každé správne WC. Porcelánová záchodová misa, na ktorú sa dá sadnúť a potrubia, ktoré sa starajú o samotný odsun a prísun toho, čo treba. Tá misa je akýmsi nadstavcom k potrubiam, aby sa dali ľahšie použiť.
  2. meno a email – ak si Git nainštaluješ a začneš ho používať, je pravdepodobné, že pri niektorom z prvých príkazov od teba bude pýtať meno a email. Nehanbi sa ich poskytnúť. Tvoje meno bude zobrazené pri commitoch a email tiež nájde svoje uplatnenie (napr. zostavovací server Jenkins ho dokáže použiť a pomocou neho poslať email autorovi commitu, ktorý spustil zostavenie) konfigurácia git email a meno
  3. dlhé vs. krátke parametre – niektoré parametre príkazov existujú v dvoch verziách. Krátkej a dlhej. Napríklad parameter so správou pre príkaz commit sa dá napísať takto:
    >git commit -m „Text správy …“alebo>git commit –message „Text správy …“Všimni si jednej pomlčky pri krátkom výraze a dvoch pri dlhom.
  4. help – každý príkaz ma svoju man stránku, ktorá sa dá zobraziť takto:> git help <názov príkazu>

Git je komplikovaný nástroj s mnohými možnosťami a zároveň je dobre dokumentovaný. Bola by škoda nevyužiť jeho plný potenciál.

Rekapitulácia základov Git

Predtým, než pôjdeme ďalej, je dobré si zhrnúť základné poznatky o tom, čo to vlastne znamená mať na disku repozitár:

  • repozitár je v podstate obyčajný adresár, ktorý má v sebe .git priečinok, v ktorom má Git uložené všetky potrebné údaje.
  • všetko ostatné v danom priečinku (vrátane podpriečinkov) je považované za working copy.
  • zmeny, ktoré sa majú uložiť v rámci commitu do repozitára musia byť najprv vložené do staged changes – to je miesta, kde sa tieto zmeny akumulujú až do najbližšieho commitu. Zmeny zo staged changes sú zaradené do najbližšieho commitu.

Git základné príkazy

Prezeranie histórie

Teraz sa pozrieme trochu bližšie na prezeranie histórie. Ešte predtým si ale v našom pokusnom repozitáry vytvoríme ďalší commit, aby sa bolo na čo pozerať. Takže ako prvé je potrebné zmodifikovať súbor index.html – doplníme znak „!“ na konci vety, takže po novom bude obsah „Hello world!“. Následne túto zmenu pridáme do staged changes:

> git add index.html

a commitneme

> git commit -m „Oprava textu“

[master 113ab5b] Oprava textu

1 file changed, 1 insertion(+), 1 deletion(-)

A teraz sa už môžeme vrhnúť na prezeranie histórie. Začneme príkazom git log:

> git log

commit 113ab5bc04fdd2d61d8c9ce3c5cb7080786a1dc2

Author: Miroslav Reiter <miroslav.reiter@it-academy.sk>

Date:   Tue Mar 15 21:46:47 2021 +0100

Oprava textu

commit e4c0627bb8819340331ca6a42bde1bb0cd24bb19

Author: Miroslav Reiter <miroslav.reiter@it-academy.sk>

Date:   Mon Mar 14 21:40:50 2021 +0100

Začiatok práce na stránke

Git logy história

To, na čo sa pozeráš, sú zoradené (najnovší hore) commity v tvojom master branchy. Každý commit má definovaného svojho autora, dátum a čas, obsah správy a svoj SHA1 hash (ten budeš mať určite iný ako ja, keďže je v ňom zahrnutý dátum a čas vytvorenia, ako aj údaje o autorovi commitu). To usporiadane ale nemusí ísť nutne časovo za sebou, pretože pre Git je podstatné poradie commitov ako ich jednotlivé časy. Ak sa Git pri commitoch neriadi časom tak čím? Každý commit (okrem toho úplne prvého, ktorý vytvoril repozitár – tzv. root commit) ma definovaného minimálne jedného rodiča. To je iný commit, na ktorý sa jeho potomok odkazuje. Commity tak vytvárajú niečo, čo sa nazýva acyklický smerový graf.

Git príkazy commity

Graf je matematická štruktúra, kde sú jednotlivé body spojené priamkami. Smerová znamená, že na každej priame je definovaný smer (teda priamka je vlastne šípka). A acyklický znamená, že v grafe neexistujú cykly. Inak, ak by si vyštartoval z ľubovoľného bodu a pohyboval sa po jednotlivých priamkach medzi bodmi, tak sa nemôže stať, že sa vrátiš do toho istého bodu. Dôležité je poznamenať, že v Gite nie je smerovanie grafu v smere ako pribúdajú commity, ale opačné – teda proti toku práce a času (commit má odkaz na predchádzajúci commit – tzv. rodičovský commit).

Orientovaný smerový graf

Repozitár začína root commitom a následne sa pridávajú ďalšie. K vetveniu môže dôjsť, keď sa vytvorí branch, ktorý sme tu už skôr spomínali. Branch je vlastne osobitná vetva kódu, ktorá v čase vytvorenia je kópiu pôvodného branchu, ale inak sa vyvíja nezávisle od pôvodnej vetvy. Branchovanie je technika, ktorá ma obrovské uplatnenie v mnohých oblastiach vývoja softvéru. Od vytvárania dočasných branchov pre izolovanie práce na jednej úlohe/chybe, cez branchovanie na oddelenie viac a menej stabilných vetví, až po branche pre jednotlivé zverejnené verzie aplikácie.

Git branche vetvy

A to som len škrtol povrch možností, čo sa dá s týmto nástrojom robiť. Plné popísanie rôznych vzorov vetvenia zdrojových kódov by znamenalo niekoľko ďalších článkov. Verzionovací systém je totiž jeden z tých nástrojov, ktoré sa majú prispôsobovať životnému cyklu aplikácie (a nie naopak). A práve preto je dôležitá jeho veľká pružnosť, ktorá ti umožní si vymodelovať štruktúru, aby sedela na aktuálny projekt. K tomu, ako vytvárať branche a ďalej s nimi pracovať, sa ešte vrátime v ďalších článkoch.

Git skupinové zmeny vetvy branch

Zatiaľ späť k príkazu git log. Je to príkaz, ktorý ma obrovské množstvo prepínačov, ktoré dokážu filtrovať alebo formátovať výstup (ak si zadáš git help log, tak získaš prehľad, o čom hovorím). Na podrobný popis všetkého nie je priestor, ale ako príklad si môžeme ukázať ešte tento variant:

> git log –oneline –graph

* 113ab5b Oprava textu

* e4c0627 Zaciatok prace na stranke

Je to rovnaký zoznam ako v predchádzajúcom prípade, len pekne zhustený so skrátenými hasmi. Z commitu sa v takom prípade zobrazuje prvý riadok commit message. Preto je pri nich odporúčaný formát, kde prvý riadok popisuje stručne zmenu (niečo ako predmet pri emaile), nasleduje prázdny riadok a potom text popisujúci commit. Ja viem. Poviete si, ako to mám všetko zapísať do príkazového riadku pri commite? Ak správu s prepínačom nezadáte, tak si Git automaticky otvorí editor (ktorý má nastavený ako východzí, čo sa dá zmeniť v nastaveniach) a nechá vám správu zapísať. Ak to Gitu vyslovene neprikážete, tak vás nepustí vytvoriť commit bez správy (čo síce môže vyzerať tyransky, ale v skutočnosti ťa učí disciplíne, ktorá je v projektoch na dlhé trate na nezaplatenie). Tie hviezdičky naľavo vo výpise git log nie sú na skrášlenie, ale predstavujú graf commitov. Akurát že zatiaľ je to taký veľmi jednoduchý graf s dvoma bodmi. Prídu aj zložitejšie.

Ako ďalší príkaz archeologického výskumu (teda rýpania sa v histórii) je git show. Ten slúži na zobrazenie informácie o jednom vybranom commite. Takže príklad:

> git show 113ab5b

commit 113ab5bc04fdd2d61d8c9ce3c5cb7080786a1dc2

Author: Miroslav Reiter <miroslav.reiter@it-academy.sk>

Date:   Tue Mar 15 21:46:47 2021 +0100

Oprava textu

diff –git a/index.html b/index.html

index 70c379b..6769dd6 100644

— a/index.html

+++ b/index.html

@@ -1 +1 @@

-Hello world

\ No newline at end of file

+Hello world!

\ No newline at end of file

Čo nám git show ukázal? Začína to základným výpisom údajov, ktorý sme videli už predtým. Potom nasleduje takzvaný diff. Hneď prvý riadok v podstate popisuje to, o čo sa akože Git snaží. Spustí diff príkaz (presnejšie diff príkaz s výstupom v Unified formáte) nad dvoma súbormi. Tie súbory sú ale virtuálne, lebo v skutočnosti sú to len dve verzie toho istého súboru. Výsledok je ale rovnaký ako keby sme diffovali dva rôzne súbory. Tak ako git log aj git show má viacero prepínačov, ktorými sa dá ovládať jeho výstup.

Z príkazov pre históriu stojí za to ešte spomenúť git shortlog a git blame. git shortlog slúži na získanie výstupu, ktorý sa podobá changelogu pri zverejnení novej verzie. Ak ho spustíme nad našim priečinkom, dostaneme niečo takéto:

> git shortlog

Miroslav Reiter(2):

Začiatok práce na stránke

Oprava textu

Pri viacerých autoroch commitu by sme získali takýto zoznam pre každého z nich.

git blame je príkaz z trochu iného súdku ako tieto doteraz. Jeho hlavnou úlohou je nájsť, ktorý commit (a teda aj informáciu o jeho autorovi a dátume/čase) ako posledný zmenil daný riadok v súbore. Poďme teda na to:

> git blame index.html

113ab5bc (Miroslav Reiter 2021-03-15 21:46:47 +0100 1) Hello world!

Skúmaný súbor má len jeden riadok a preto ani výstup git blame viac neobsahuje. Ak by ich bolo viac, tak by bola takáto informácia vypísaná pre každý jeden. Na teraz stačilo hrabania sa v minulosti a poďme sa radšej pozrieť, ako sa formuje budúcnosť.

Ignorovanie súborov a zmien

Hlavný účel Git repozitára je sledovanie a verzionovanie zmien súborov. Existujú ale prípady, kedy sa vo working copy môžu nachádzať súbory, ktoré si Git nemá všímať. Sú to napríklad súbory s nastaveniami pre IDE, ktoré sú privátne pre každého vývojára. Alebo generované súbory, ktoré vznikajú pri kompilácii projektu, prípadne inom automatizovanom projekte. To sú súbory, ktoré dávať do repozitára by bolo zbytočné, zároveň by nás ale Git štandardne upozorňoval, že sa nachádzajú vo working copy (pri výpise git status) a on nevie čo s nimi. Preto existuje niekoľko spôsobov ako Gitu povedať, aby si tieto súbory nevšímal. Ten najčastejšie používaný je pomocou .gitignore súboru. Je to súbor, ktorý sa zvykne umiestňovať do koreňového priečinka repozitára a obsahuje zoznam súborov, ktoré má git ignorovať. Príklad obsahu takéhoto súboru je:

  • *.class
  • # Mobile Tools for Java (J2ME)
  • .mtj.tmp/
  • # Package Files #
  • *.jar
  • *.war
  • *.ear

Toto je začiatok súboru .gitignore odporúčaného pre Java projekty. Na GitHube existuje projekt, kde viete nájsť pripravený .gitignore súbor pre veľa rôznych programovacích jazykov. Čo teda .gitignore môže obsahovať:

  • cestu k súboru, ktorý sa má ignorovať (podporované sú wildcards alias zástupné znaky ako je napríklad * pre ľubovoľný počet znakov)
  • cestu k priečinku, pričom sa v nej dá použiť reťazec **, ktorý ak:
  • je pred názvom priečinku (**/foo) znamená, že je platný pre ľubovoľný podpriečinok foo kdekoľvek vo working copy
  • je ako posledný v ceste (foo/**), znamená všetky súbory v danom priečinku
  • je niekde uprostred (bar/**/foo), znamená všetky priečinky, ktorých cesta začína na bar a končí na foo (vrátane bar/foo)
  • komentár začínajú znakom #
  • negáciu podmienky začínajúcu na !

Osobne som sa nestretol zatiaľ ani s jedným projektom, ktorý by nejakým spôsobom .gitignore súbor nepoužíval. Aj vzhľadom na túto funkčnosť Gitu si môžeme povedať, že git rozpoznáva 3 druhy súborov:

  1. sledovaný (tracked) – súbor bol pomocou git add zaradený do repozitára
  2. ignorovaný (ignored) – súbor bol vylúčený zo spravovania pomocou Gitu
  3. nesledovaný (untracked) – ostatné súbory, ktoré nespadajú do prvý dvoch kategórií

Tak fajn, vieme ignorovať celé súbory, ale čo s prípadom, kedy chcem, aby bol súbor v repozitáry a ignorovaná bola len nejaká konkrétna zmena? A kedy vôbec niečo také budeme potrebovať? Ako príklad môže slúžiť konfiguračný súbor, ktorý je potrebné, aby v repozitáry bol (používa sa pri nasadení aplikácie, ale aby v tomto súbore mal každý vývojár nejakú hodnotu inú ako ostatní (techník ako sa s tým vysporiadať, ak máte po ruke nástroje automatizácie, je veľa, ak sa ale súbor často nemení a tím vývojárov nie je veľký, tak najjednoduchšie je, čo si teraz popíšeme). Postup je teda taký, že do repozitára sa umiestni správna verzia súboru, ktorá obsahuje nastavenia pre nasadzovanie, následne si vývojár tento súbor zmodifikuje a už len Gitu povie, aby ignoroval zmeny v ňom. Poďme si to teda skúsiť. Najprv v našom súbore urobím zmenu, tak že na koniec riadku doplním nový znak:

Hello world!?

Súbor je modifikovaný a git ho tak aj vidí:

> git status –short

M index.html

Použili sme skrátenú verziu výpisu – to M na začiatku je skratka od modified. Následne pomocou príkazu git update-index –assume-unchanged Gitu poviem, aby zmenu ignoroval:

> git update-index –assume-unchanged index.html

Ďalšie spustenie git status nám potvrdí, že Git už žiadnu zmenu nevidí:

> git status –short

Skrátená verzia git status neukázala nič, čo znamená, že Git nevidí žiadne zmeny vo working copy. Príkaz, ktorý sme v skutočnosti použili, je vlastne git update-index, ktorý má omnoho širšie použitie ako len ignorovanie zmien, ale pre tento moment ostaneme len pri tomto. index.html súbor je teraz v stave, že akékoľvek ďalšie zmeny v ňom sú ignorované. Čo ale spraviť, ak predsa len chcem, aby sa nejaká zmena mohla commitnuť a dostať tak do repozitára. Na to slúži prepínač –no-assume-unchanged, ktorým tento súbor vrátim medzi štandardné sledované súbory:

> git update-index –no-assume-inchanged index.html

A znova kontrola stavu:

> git status –short

M index.html

Odstraňovanie súborov

Ak potrebujete odstrániť súbor z projektu, Git ponúka príkaz git rm. Tento príkaz odstráni súbor z pracovného adresára aj zo staging area.

Príklady:

git rm hello.py # Odstránenie súboru
git commit -m „Odstránenie hello.py“ # Commitovanie zmien

Zobrazenie stavu projektu

Príkaz git status je užitočný na zobrazenie aktuálneho stavu pracovného adresára a staging area. Ukazuje, ktoré súbory boli zmenené, pridané alebo odstránené.

Príklady:

git status # Zobrazenie stavu projektu

Zobrazenie rozdielov

Príkaz git diff umožňuje zobraziť rozdiely medzi pracovným adresárom, staging area a posledným commitom. Tento príkaz je užitočný na prehľad zmien pred commitovaním.

Príklady:

git diff # Zobrazenie rozdielov v pracovnom adresári
git diff –cached # Zobrazenie rozdielov v staging area

Riešenie konfliktov

Konflikty môžu nastať, keď sa zmeny v rôznych vetvách dotýkajú rovnakých častí súborov. Git označí tieto konflikty a umožní vám ich manuálne vyriešiť.

Kroky pri riešení konfliktov:

  1. Otvorte konfliktný súbor v textovom editore
  2. Manuálne upravte konfliktné časti podľa potreby
  3. Odstráňte značky konfliktov (<<<<<<, ======, >>>>>>)
  4. Potvrďte vyriešenie konfliktov príkazmi git add a git commit

Príklady:

git add konfliktný_súbor
git commit -m „Riešenie konfliktu pri zlúčení“

Práca s Git ignore

Súbor .gitignore umožňuje špecifikovať súbory a adresáre, ktoré Git nemá sledovať. Tento súbor je užitočný na vylúčenie dočasných súborov, kompilovaných súborov a iných nepotrebných položiek z repozitára.

Príklad .gitignore:

# Ignorovanie kompilovaných súborov
*.o
*.a
*.out

# Ignorovanie dočasných súborov
*.tmp
*.swp

# Ignorovanie adresára build
build/

Pridanie .gitignore do repozitára:

echo „*.o“ >> .gitignore # Pridanie pravidla do .gitignore
git add .gitignore # Pridanie .gitignore do staging area
git commit -m „Pridanie .gitignore na ignorovanie kompilovaných súborov“ # Commitovanie zmien

Záver a sumarizácia

Lokálna práca so súbormi v Gite je základom efektívnej správy verzií. Používanie príkazov na pridávanie, úpravu, odstránenie a commitovanie súborov vám umožní udržiavať prehľadnú históriu vášho projektu a efektívne riešiť konflikty. Práca s .gitignore súborom vám pomôže udržiavať váš repozitár čistý a bez zbytočných súborov. Hlavným účelom repozitárového systému je sledovanie verzií súborov. Aj preto sme sa hneď v tomto prvom praktickom diely o Gite venovali práci s históriou a súbormi. Dôležité je uvedomiť si, že všetky zmeny ktoré sú zaznamenávané, sa dejú len na základe commitov a že tie majú svoju pevnú postupnosť. Na základe týchto nemenných pravidiel je potom možné cestovať hore dole v čase a získať akúkoľvek verziu súborov. V ďalšom diely budeme pokračovať v práci so súbormi, a tiež si povieme, prečo je pre Git dôležitejší obsah než forma.

Objavte online kurzy na Git a GitHub

Odporúčania na prácu s GITom

Pri práci s Gitom dbajte na pravidelné commitovanie zmien, používanie vetiev na izolovanie rôznych častí projektu a sledovanie stavu projektu pomocou git status. Tieto postupy vám pomôžu udržiavať váš projekt organizovaný a efektívny.

Prehľad publikovaných článkov

  1. Seriál Online kurz Git – Začíname s Gitom – 1. diel
  2. Seriál Online kurz Git – Lokálna Práca so Súbormi – 2. diel
  3. Seriál Online kurz Git – V Hlbinách Súborového Systému – 3. diel
  4. Seriál Online kurz Git – Paralelné svety a Git branch – 4. diel
  5. Seriál Online kurz Git – Mergovanie s Konfliktom, Tagy a Skrytie Zmien – 5. diel
  6. Seriál Online kurz Git – Vzdialené repozitáre, GitHub, Bitbucket – 6. diel
  7. Seriál Online kurz Git – Clean, Reset, Rebase, Revert nástroje do každého počasia – 7. diel
  8. Seriál Online kurz Git – Najčastejšie problémy, faily a fuckupy – 8. diel

Autor

Miroslav Reiter

Programátor, manažér a marketér, ktorý mudruje vo vlastnej vzdelávacej spoločnosti IT Academy. Workoholik so 134 certifikáciami a 13 titulmi. Vytvoril som vzdelávaciu platformu vita.sk, pretože milujem vzdelávanie a všetko čo k nemu patrí. Pomáham firmám ale aj jednotlivcom zlepšovať ich podnikanie a IT. Certifikácie: Microsoft certifikovaný tréner, Google certifikovaný tréner, ITIL, PRINCE2 tréner. 40000+ vyškolených klientov a 1000+ firiem, ktorým som pomohol Referencie: Národná Rada SR, Slovnaft, IBM, Panasonic, Ministerstvo obrany SR, ČSOB, Generali, Tatra banka, Európska komisia, SPP, Pixel Federation, ESET.