Kihagyás

2. gyakorlat: Git

Szerkesztés alatt!

Az oldal további része szerkesztés alatt áll, a tartalma minden további értesítés nélkül többször, gyakran, jelentősen megváltozhat!

Verziókövetés

A verziókövetés lényegében valamilyen információ - például a forráskód, fájlok, mappák - több változatának menedzselése.

Ez megtehető "manuálisan" is, fájlok, mappák átnevezésével, verziószámozásával, de ilyet manapság nem csinálunk!

ilyet-ne

Helyette verziókövető rendszereket használunk, amik:

  • Nyomon követik, hogy mikor és hogyan változtak a fájljaink, mappáink és ki végezte el a változtatást.
  • A mappák, fájlok bármelyik korábbi (rögzített) állapota visszaállítható, illetve lekérhető a legfrissebb verzió.
  • Szinkronizálni tudják a mi változatainkat egy másik gépen levő hasonló mappával (átvezetve a változásokat).
    • Jelzik, ha ezt nem tudják automatikusan elvégezni.
  • Minden verziót egy egyedi azonosítóval (számmal vagy hash-sel) azonosítanak.
  • Nyilvántartják a verziók közötti összefüggéseket (amik a legegyszerűbben egy gráffal vizualizálhatók).

Azaz innentől kezdve nincs szükség arra, hogy a fájlok elnevezésével jelöljük meg a különböző verziókat, hiszen szoftveres módon fogjuk tudni kezelni a problémát.

Sokféle verziókövető rendszer létezik, ezek között kisebb-nagyobb különbségek vannak:

  • CVS
  • SVN
  • Git
  • Mercurial
  • GNU Bazaar
  • IBM ClearCase
  • Visual SourceSafe
  • ...

Mi a talán legismertebbel, és manapság legnépszerűbbel, a Git-tel fogunk megismerkedni.

Verziókövetés fogalmak

A félév során Git verziókövető rendszert fogunk használni, így az alábbi fogalmak is elsősorban erre a verziókezelő szoftverre vonatkoznak.

  • repository: a forráskódok, history (korábbi események) tárhelye (repó néven is hivatkozunk majd rá)
    • remote repository: egy távoli gépen (általában szerveren) tárolt repository, általában staging area és working copy nélkül
    • local repository: a saját gépen tárolt repository, amiben dolgozunk, amihez staging area és working copy is tartozik
  • clone: remote repository lemásolása a saját gépre (első alkalommal)
  • working copy (working directory): aktuális munkakönyvtár egy adott repository-hoz
  • staging area: átmeneti terület a local repository és a working directory között, a következő commit-ra jelölt fájlokat tartalmazza
  • commit: a fájlok, változások eltárolása a local repository-ban
  • push: a local repository változásainak (commit-jainak) feltöltése a remote repository-ra
  • fetch: a remote repository változásainak (commit-jainak) letöltése a local repository-ba
  • pull: egy fetch, merge és checkout; a remote repository változásainak letöltése a local repository-ba, ha kell (és lehet) akkor az eltérések automatikus feloldása, és a working copy updatelése az aktuális branch-en
  • branch: különböző elágazások a fejlesztésben, amelyek később visszatér(het)nek a main-be
  • main: a fő fejlesztési irányvonal, egy kitüntetett és általában jobban védett branch
  • checkout: a working copy elemeit módosítja a staging area és/vagy local repository-ből, például branch-ek váltása esetén
  • HEAD: a working copy alapjául szolgáló verzióra való hivatkozás
  • merge: branch-ek egyesítése
  • conflict: ha ugyanaz a dokumentum mindkét merge-elendő branch-ben megváltozott (a két branch közös őse óta), és a változtatások nem egyesíthetők automatikusan

git-versioncontrol

branches

Git specifikus fogalmak

Bár minden verziókezelő célja alapvetően ugyanaz, és nagyjából ugyanazokból az elemekből építkeznek, mégis, néhány fenti fogalom más verziókezelő - például SVN - esetén nem értelmezhető vagy mást jelent. Ezért, más verziókezelők használata esetén oda kell figyelni az abban használt fogalmak jelentésére.

Mit verziókövessünk Git-ben?

A Git verziókezelő rendszer alapvetően a szöveges állományok, így tipikusan a forráskód fájlok, plain text dokumentációk változáskezelésében hatékony. Ez azt is jelenti, hogy bizonyos fájlokat nem érdemes Git-tel verziókövetni (bizonyos nézőpontból pedig nem csak nem érdemes, de elvi hiba is, hiszen a Git nem tárhelyszolgáltatásként működik). Valamint, a szöveges állományok közül szintén nem érdemes azokat tárolni, amelyek a többi segítségével automatikusan és egyértelműen generálhatók (bár ezen ökölszabály alól is lehetnek kivételek). Így tehát Git-ben NE tároljunk:

  • futtatható állományokat (pl. linux programok, *.exe)
  • tömörített mappákat (pl. *.jar, *.rar, *.zip)
  • bináris fájlokat és csak ilyeneket tartalmazó mappákat (pl. bin/, *.class, *.png, *.jpg)
  • generált fájlokat és mappákat (pl. build/, tmp/, *.class, *.tmp, *.log)

Repository létrehozása

Git repository és GitLab projekt

Ami a Git-ben egy repository, az a GitLab-on egy projekt alapja, egy GitLab projekt egy konkrét Git repository-hoz nyújt kiegészítő támogatást.

Az előző órán szó volt a GitLab-ról, mint a Git "fölé" épülő, annak funkcióit kényelmesebben kezelhetővé tevő és kibővítő szoftverről. Amikor a GitLab-on létrehozunk egy projektet, akkor létrejön egy hozzá tartozó Git repository is. Ez azt jelenti, hogy mindenki legalább két Git repository-hoz hozzáfér a Hallgatói Demonstrációs GitLab Szerveren:

  • a saját csoportjának közös folyamatok nevű projektjének repójához, és
  • a saját maga által az adott csoportban SDP25-hxxxxxx néven létrehozott projektjének repójához.

Ezen repository-k URL-je https://git-okt.sed.inf.szte.hu/sdp25-szoftverfejlesztesifolymatok/SDP25-IBNa1017L-%/folyamatok.git, illetve https://git-okt.sed.inf.szte.hu/sdp25-szoftverfejlesztesifolymatok/SDP25-IBNa1017L-%/{'name': 'SDP25-hxxxxxx', 'slug': 'SPD25-hxxxxxx', 'temp': 'hxxxxxx'}.git, ahol a % helyére a csoport sorszámát, a hxxxxxx helyére pedig a saját h-s azonosítót kell behelyettesíteni. A továbbiakban ezeket mint remote repository-kat fogjuk használni.

Remote repository és central repository

Vannak központosított és elosztott verziókezelők.

A központosított verziókezelők (mint például az SVN) jellemzője, hogy van egy központi szerver, és az felel a verziók nyilvántartásáért; a klienseken általában csak a working copy és staging area (illetve az adott verziókezelő ezeknek megfelelő elemei) találhatóak meg. Vagyis a teljes repository csak egyetlen helyen van nyilvántartva.

Az elosztott verziókezelők esetében (mint például a Git) a teljes repository minden kliensnél megtalálható. Így tulajdonképpen nem is lenne szükség szerverre, a Git köszöni szépen, local repository-ként a helyi könyvtárban is nagyon jól megvan. Ha viszont többen dolgoznak egyszerre a projekten, mindenki saját gépen, akkor az azt jelentené, hogy több repository van, mindenkinek van egy saját local repository-ja. Az ugyan igaz, hogy remote repository-ként bárki bármelyik másik fejlesztő repóját el tudná érni, de a teljes szinkronizálás (hogy mindenkinél ugyanaz a repository legyen meg) ilyen esetben rémálom lenne. Ezért az elosztott verziókezelők esetén is ki szokás jelölni egy kitüntetett, központi repository-t, amit minden fejlesztő beállít magának remote repository-ként, és mindenki ezzel szinkronizál. Ez a központi repó (általában) egy úgynevezett bare repository, és nem tartozik hozzá staging area és working copy.

A fent említet, GitLab szerveren található repók ilyen, csak remote repository-ként használható bare repository-k.

És hogyan lesz ezekből local repository-nk? Klónozással!

git kliensek

Sokféle Git kliens létezik (bár a "kliens" elnevezés a Git filozófiája miatt nem biztos, hogy megállja a helyét). Mi alapvetően a parancssori git-tel fogunk megismerkedni. Linux alatt ez a git csomag telepítése után terminálból használható, Windows alatt pedig például a git bash-ben lehet a git parancsokat használni.

Repository klónozása

Gyakorlatvezetői feladat: README.md

Mielőtt a hallgatók klónozzák a sdp25-szoftverfejlesztesifolymatok/SDP25-IBNa1017L-%/folyamatok.git repository-t, a README.md fájlban hozzunk létre egy Csoporttagok: nevű részt (a felesleges dolgokat pedig törölhetjük). A hallgatók majd ide fogják listaelemként beírni a saját nevüket.

Ha már létezik egy repository, amit mi remote repository-ként használnánk, és szeretnénk belőle egy vele ekvivalens local repository-t, akkor ezt a repository-t klónozhatjuk a git clone paranccsal. Ennek egy vagy két további paramétere van:

  • A remote repository elérhetősége (kötelező), ami általában egy URL (https://user@gitlab.server.url/path/to/project.git) vagy egy SSH könyvtár URI (user@gitlab.server.url:path/to/project.git), de lehet lokális könyvtár is.
  • A könyvtár neve (opcionális), amibe a repository kerül. Ha ezt nem adjuk meg, akkor az URL project név része lesz használva.
1
2
git clone https://git-okt.sed.inf.szte.hu/sdp25-szoftverfejlesztesifolymatok/SDP25-IBNa1017L-%/folyamatok.git
git clone https://hxxxxxx@git-okt.sed.inf.szte.hu/sdp25-szoftverfejlesztesifolymatok/SDP25-IBNa1017L-%/folyamatok.git
Feladat: klónozd le a gyakorlati csoportod közös és saját repository-ját

Klónozd le a Hallgatói Demonstrációs GitLab Szerverről a SDP25-SzoftverfejlesztesiFolymatok csoport saját gyakoraltodhoz tartozó SDP25-IBNa1017L-% alcsoportjából a közös folyamatok és saját SDP25-hxxxxxx nevű projekteket.

Projekt és repository nevek

Figyelj arra, hogy a GitLab-on látható csoport és projektnevek (SDP25-SzoftverfejlesztesiFolymatok, SDP25-IBNa1017L-%, folyamatok, SDP25-hxxxxxx) nem feltétlenül egyeznek meg a projekt elérhetőségében található nevekkel (sdp25-szoftverfejlesztesifolymatok, SDP25-IBNa1017L-%, folyamatok.git, SPD25-hxxxxxx.git)!

A géptermekben figyelj arra, hogy hol, melyik könyvtárban dolgozol!

A számítógépes géptermekben a gépek helyi meghajtói minden újraindításkor törlődnek. Ha ide dolgozol, akkor a local repository-d abban a pillanatban elveszik, amikor kilépsz a gépről. Ezért érdemes felmountolni a saját home könyvtáradat, és abban dolgozni; legalább addig, amíg nem tudod szinkronizálni a local repository-t a remote repository-val. Ha ezt már meg tudod tenni, és a géptől való távozás előtt meg is teszed, akkor egy újabb klónozással már meglesznek a legutóbbi verzióid; ilyenkor legfeljebb a személyazonosság beállításával kell majd minden klónozás után bajlódnod.

Local repository beállításai

A git repository-nkat, illetve az adott gépen lévő összes local repository default beállításait a git config parancs segítségével tudjuk konfigurálni. A legfontosabb dolog a személyazonosság beállítása. Ezt saját tulajdonú gépen alapvetően érdemes globálisan beállítani. (A géptermekben pedig minden, a home könyvtáradba klónozott repository-hoz egyenként, azaz --global kapcsoló nélkül.)

1
2
git config --global user.name "User Name"
git config --global user.email "user@email.address"

Egy adott local repository-n belül a --global kapcsoló elhagyásával a fenti értékeket az adott repóra vonatkozóan felülírhatjuk. Bármely, az adott gépen és repóban végzett Git tevékenységet a Git a beállított személyazonossághoz fog kapcsolni, függetlenül attól, hogy a GitLab szervert milyen identitással érjük el.

A beállítások listáját, illetve egy-egy settings.id nevű beállítás konkrét értékét a git config --list illetve git config settings.id parancsokkal kérhetjük le (mindkettőnél használható a --global kapcsoló).

Feladat: Személyazonosság beállítása

Állítsd be a nevedet és az e-mail címedet a Git-ben a git config parancsok segítségével.

Munka a local repository-ban

Egy Git által verziókezelt könyvtárban háromféle "terület" van:

  • working copy: Ez a könyvtár aktuális állapota. Az állapotot általában a staging area-hoz, vagy egy konkrét verzióhoz (a HEAD referenciával hivatkozott verzióhoz) képest értelmezzük.
  • staging area: A working copy és a local repository közötti ideiglenes verzió. Ide kerülnek azok a (tartalmi és fájlrendszerbeli) változtatások a working copy-ból, amit majd a következő tárolt verzióba belerakunk. Ezt is a HEAD verzióhoz képest értelmezzük.
  • local repository: A verziókezelt könyvtár összes tárolt verziója.

A branch kiválasztása

Egy projekt során általában több fejlesztés is fut egyszerre, ezek a repository-ban általában külön branch-ként jelennek meg. Minden branch-hez több commit, azaz verzió tartozhat. Ha a fejlesztésnek vége, akkor az adott branch-en elvégzett változtatásokat be lehet merge-elni a main-be (és az adott branch-et törölni lehet, de ezt fejlesztése válogatja).

Új branch a git branch paranccsal készíthető.

1
git branch uj-branch-neve

Ilyenkor az aktuális verzióból (a HEAD-ből) kiágaztatunk egy új fejlesztési ágat. Ez ilyenkor még nem lesz automatikusan a working copy alapja, ennek kiválasztására a git checkout parancs szolgál.

1
git checkout uj-branch-neve
A git checkout parancs

A git checkout jóval többet tud, mint egy branch kiválasztása. Igazából bármilyen tárolt verziót (egyedi commit-ot) checkout-olhatunk, onnantól ez lesz a working copy "alapja". Sőt, egyes fájlok állapotát külön-külön is vissza tudjuk vele állítani a tárolt verzióra.

A fenti két parancs, azaz egy új branch létrehozása és beállítása mint a working copy alapja egyben is megoldható.

1
git checkout -b uj-branch-neve
Feladat: saját branch létrehozása

A folyamatok repository-ban hozz létre egy saját branch-et, melynek neve a h-s azonosítód, és állítsd be ezt a branch-et a working copy alapjának!

Következő verzió kialakítása

A working copy állapotának ellenőrzésére a

1
2
3
git status
git diff
git diff --staged

parancsok használhatók. A working copy változásait a

1
2
git add ...
git rm ...

parancsokkal tudjuk a staging area-ba átrakni. A git add a megadott fájlok aktuális verzióit adja hozzá (akár verziókezelt volt előtte a fájl (változtatás), akár nem (hozzáadás)), míg a git rm parancs törli az adott fájlokat az adott verzióból (egyelőre staging area-ból).

Fájlok hozzáadása és törlése

Az talán egyszerűen látható/elképzelhető, hogy ha a working copy-ban létrehozunk egy fájlt, az a megfelelő git add parancs végrehajtásáig nem kerül bele a következő verzióba, a Git "nem fog emlékezni" rá. Ha már létező (verziókezelt) fájlt módosítunk, de ezt nem jeleztük a Git felé a megfelelő git add paranccsal, a Git akkor nem fogja figyelembe venni a változtatásunkat a következő verzióban. Az már kevésbé nyilvánvaló, hogy ha törlünk egy fájlt a working copy-ból, az a git rm parancs kiadásáig nem fog törlődni a következő verzióból. Vagyis hiába törlünk "csak úgy" egy fájlt a Git értesítése nélkül, a Git az ilyen fájlokat (az előző verzióhoz képest) változatlannak fogja tekinteni.

Feladat: fájl módosítása

A csoport közös folyamatok nevű repository-jában a README.md fájl Csoporttagok: pontja alá írd be a nevedet.

  • Mit mutat a git status parancs?
git status
1
2
3
4
5
6
7
8
9
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
  • Mit mutat a git diff parancs?
git diff

A parancs kimenete valami hasonló lesz, attól függően, hogy pontosan mi is volt a README.md eredeti tartalma:

1
2
3
4
5
6
7
8
9
diff --git a/README.md b/README.md
index 9509f11..0f19286 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,5 @@

 ## Csoporttagok

+- Saját Neved

Feladat: változás hozzáadása

A README.md fájlban történt változtatást add hozzá a staging area-hoz.

  • Most mit mutat a git status parancs?
git status
1
2
3
4
5
6
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   README.md
  • Mit mutat a git diff parancs?
git diff

A parancs kimenete üres lesz.

1

  • Mit mutat a git diff --staged parancs?
git diff --staged

A parancs kimenete valami hasonló lesz, attól függően, hogy pontosan mi is volt a README.md eredeti tartalma.

1
2
3
4
5
6
7
8
9
diff --git a/README.md b/README.md
index 9509f11..0f19286 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,5 @@

 ## Csoporttagok

+- Saját Neved

Új verzió készítése

A staging area-ban tárolt változtatásokból az aktuális branch egy új verzióját, azaz egy commit-ot, a git commit parancs segítségével tudjuk létrehozni.

1
git commit -m "Commit message"

A commit message az aktuális verzióban található változtatások rövid leírása. A parancs kiadása után a változások egy új commit formájában bekerülnek a local repository-ba. A repository commit-jait a git log parancs segítségével tudjuk megnézni. Minden commit-hoz tartozik egy egyedi azonosító, egy úgynevezett commit hash. Fel van továbbá tüntetve a szerző (ahogy a Git konfigurációjában szerepel, és nem a GitLab user), a dátum, valamint a fentebb említett commit message.

A git log paraméterezhetősége

A git log parancsa alapvetően az adott branch korábbi commit-jait mutatja, listában, részletesen. Viszont sokféleképpen felparaméterezhető, ami egy bonyolultabb, több itt-ott összeérő branch-et tartalmazó fejlesztés esetén jól jöhet. Pl:

1
git log --oneline --decorate --graph --color --all

Feladat: commit elkészítése

Készíts egy commit-ot, a commit message legyen a "Saját név hozzáadása a README.md listához.", vagy valami hasonló. A git log parancs segítségével nézd meg a repó commit-jait.

  • Hány commit volt eddig?
  • Kik és mikor készítették ezeket?
  • Most mi a working copy státusza?

Van tehát egy új branch-ünk, abban egy új commit, és mindezt eltároltuk a local repository-ban. Már "csak" szinkronizálni kell a remote branch-csel. A következő két gyakorlat erről a "csak"-ról fog szólni.


Házi feladatok

Házi feladat: Saját projekt klónozása

Otthon klónozd le a https://hxxxxxx@git-okt.sed.inf.szte.hu/sdp25-szoftverfejlesztesifolymatok/SDP25-IBNa1017L-%/SPD25-hxxxxxx.git URL-ről (a % és hxxxxxx részeket megfelelően kicserélve) a saját projekt repódat! Konfiguráld fel a Git-et, állítsd be a személyazonosságodat! (Legalább a saját repódban, de ha a saját gépen globálisan csinálod meg, talán az sem árt. Illetve, ha mégis ártana valamit, akkor meg valószínűleg nem lesz probléma elvégezned a feladatot. ;) )

Házi feladat: 1. mérföldkő a saját projektben

A CooSpace-en kihirdetésre kerülnek/tek az 1. mérföldkő követelményei. Ezt nézd át, és ha valamit esetleg javítanod kell, azt még a 2025-03-02 határidő előtt tedd meg!

Hogyan javítsd az esetleges hibákat?

Az előző óra utolsó házi feladata talán nyújt egy kis segítséget a projekt nevezéktannal kapcsolatos hibáinak kezeléséhez.