Git¶
Javasolt lépések az 1MF megkezdéséhez
- A projektmenedzser töltse le a minta projektterv fájlt (pl. git clone utasítással vagy .zip fájlként)
- A projektmenedzser a git clone utasítással hozza létre a projekt lokális repóját és helyezze el benne a minta projekttervet, majd töltse is fel a központi tárolóba (git add, commit, push)
- A projektmenedzser értesíti a csapattagokat, így a csapatmegbeszélésen elhangzottaknak megfelelően mindenki el tudja kezdeni a projektterv kitöltését lokálisan, szintén a projekt klónozásával
- Ha az adott csapattag végzett a kitöltéssel, akkor push-olja a változtatásokat (előfordulhat conflict, hiszen lehet, hogy egy csapattárs korábban már push-olt, ezt fel kell oldalni)
Ellenőrző kérdések a mérföldkövek zárásához
- Megvan a szükséges mennyiségű issue- és commit-szám?
- Elkészítettem és feltöltöttem a mérföldkőről az egyéni jelentést?
- A mérföldkő teljes időtartama alatt vezettem a mérföldkőben vállalt feladataimról az issue-kat?
- Egy feladat befejezését követően lezártam a saját issue-imat?
- A projektmenedzser rögzítette a csapatgyűléseket a projektdokumentációban vagy a Wiki oldalon?
Általános commit-olási tanácsok
- https://www.worklytics.co/blog/commit-early-push-often és https://www.freecodecamp.org/news/writing-good-commit-messages-a-practical-guide/ alapján:
- Bontsd le a munkádat kisebb, egységnyi commitok-ra
- Ne maradjon nem commit-olt munka a lokális repóban
- A nagy commit-ok nehezebben olvashatók mások számára
- A commit üzenet határozza meg a commit fajtáját (pl. fix, refactor, feature, stb.)
- A commit üzenet egyértelműen tükrözze a commit tartalmát
- Ne egyszavas commit üzeneteket írj, ne feltételezd, hogy a kód önmagában magyarázza a commit által tartalmazott módosítást
- A commit üzenetben hivatkozz a megfelelő issue-ra
Telepítés¶
A Git könnyen telepíthető tetszőleges operációs rendszerre: https://git-scm.com/downloads
A tárgy célja a Git rendszer alapjainak megértése (és nem egy választott grafikus felület megtanulása), így a gyakorlaton minden esetben terminálon/parancssoron keresztül tárgyaljuk a Git használatát (mindazonáltal az alapszintű megismerést követően érdemes szétnézni milyen más lehetőségek vannak: https://git-scm.com/downloads/guis).
Git utasítások¶
Git esetén az utasítások minden esetben a git
paranccsal fognak kezdődni. A következő utasítások során feltételezzük, hogy a GitLab rendszerben létehoztunk egy üres projektet teszt néven.
Azonosítás¶
Globálisan beállítjuk a nevünket és az email címünket:
git config --global user.name "Teszt Elek"
git config --global user.email "h123456@stud.u-szeged.hu"
Ezt minden esetben tegyük meg, illetve ellenőrizzük annak érdekében, hogy a GitLab rendszerében következetesen jelenjenek meg a commit-ok és a hozzátartozó információk. Az aktuális konfigbeállítást a következő utasítással kérhetjük le:
git config -l
Üres repository klónozása¶
A korábban létrehozott üres tárolót a következő módon tudjuk leklónozni:
git clone https://git-okt.sed.inf.szte.hu/markusa/teszt.git
Láthatjuk, hogy jelen esetben lokálisan is megjelent a tároló a számítógépünkön a remote repository klónozásával. Illetve fontos tudni, hogy a verziókezelő a gyökérkönyvtárban lévő .git nevezetű, rejtett mappában helyez el a verziókövetéshez nélkülözhetetlen fájlokat (pl. history), ezeket ne módosítsuk.
Fájl hozzáadása¶
Hozzunk létre egy új fájt és írjunk bele pár sort. A következő utasítással lekérhetjük a fájlok aktuális állapotát. Láthatjuk, hogy jelenleg a nevsor.txt fájlunk még nem része a staging area-nak:
git status
Ahhoz, hogy nyomonkövetett állapotba helyezzük, a következő utasítást használjuk:
git add nevsor.txt
Rekurzívan az összes módosított fájlt a következő utasítással tudjuk a "lokális adatbázishoz" hozzáadni:
git add .
A nyomonkövetés megszüntetését, azaz a staging area-ból való kivételt a következő utasítással tudjuk megtenni:
git reset nevsor.txt
A Staging area-ból a fájlunkat a local repository-ba a következő utasítással tudjuk hozzáadni:
git commit -m "nevsor.txt hozzadasa"
Amennyiben ezt a commit-ot még sem akarjuk megtartani, akkor a következőket tehetjük. Törölhetjük a legutolsó commit-ot anélkül, hogy a módosításokat is törölnénk (HEAD~1 egy speciális commit azonosító, a megelőző commit-ra mutat):
git reset --soft HEAD~1
Vagy visszaállhatunk az előző commit-ra is a változtatások törlésével (--hard esetén alkalmazhatunk HEAD~2-t is, ez a 2-vel megelőző commit-ra mutat):
git reset --hard HEAD~1
Git reset
A reset utasítás tökéletesen működik mindaddig, amíg csak a lokális repóban létrehozott új commit-okat kellett visszavonni. Azonban ha már a push utasítást kiadtuk (azaz megosztottuk a commit-jainkat a központi tárolóval, végső során tehát a többi fejlesztővel), akkor más megoldás szükséges, mivel a commit history-t mindenképpen meg szeretnénk őrizni. Egy lehetőség erre a revert parancs: https://sentry.io/answers/revert-a-git-repository-to-a-previous-commit/
Most viszont tartsuk meg a korábban létrehozott commit-ot. Jelen esetben még csak a local repository tartalmazza a commit-ot, viszont a remote repository nem. Először nézzük meg, hogy mi a remote repository elérhetősége (láthatjuk, hogy origin néven tudunk hivatkozni rá):
git remote -v
Most küldjük fel a commit-okat:
git push origin master
A GitLab-on láthatjuk, hogy meg is érkezett a commit:
Branch létrehozása¶
A fejlesztési ágak használata első ránézésre komplikáltnak tűnhet, de hosszútávon mindenképp a fejlesztés javára szolgál. Mindazonáltal (ellentmondva a Git logikájának) ezen a gyakorlaton nem kötelező a branch-ek használata, de erősen ajánlott.
Új branch létrehozásához abban a branch-ben kell lennünk, ahonnan létre szeretnénk hozni a másolatot (jelen esetben a master branch-ről dolgozunk):
git checkout -b develop
A checkout utasítás szolgál a branch-ek közötti váltásra. Jelen esetben -b kapcsolóval mondtuk meg, hogy egy új branch létrehozása a cél, amennyiben a develop branch még nem létezne és a -b kapcsolót elhagynánk, akkor hibaüzenetet kapunk. A -b kapcsoló nélkül tehát csak létező branch-ek között tudunk váltani. A következő képen látható, hogy jelenleg 2 branch létezik a local repository-ban, viszont a remote repository jelenleg még csak a master-t tartalmazza. Itt még fontos megjegyezni a git branch -vv
utasítást, ahol látható, hogy local master branch rendelkezik egy ún. upstream referenciával a remote master branch-re, viszont a local develop branch jelenleg még nem. Az upstream referencia lényege, hogy innentől kezdve a git push
és (későbbiekben látni fogjuk) git pull
utasítás önmagában használhatóak lesznek majd.
Módosítsuk a fájlunkat és töltsük fel az eredményét a remote repository-ba. Ahogy látható, először a git push
utasításra hibaüzenetet kapunk, így használnunk kell a következőt, amellyel az upstream referenciát beállítjuk:
git push -u origin develop
GitLab-ra tekintve látható, hogy immáron ott is megjelent a develop branch:
Branch-ek egyesítése¶
Térjünk vissza a master branch-re és ismét módosítsuk a fájlt. Tegyük elérhetővé a módosítást a remote repository-ban, majd egyesítsük a master branch-et a develop ággal.
Merge esetén azon a branch-en kell lennünk, amelybe a másik branch-et szeretnénk egyesíteni. Jelen esetben a master-en vagyunk és a develop-ot szeretnénk beolvasztani, így az utasításunk:
git merge develop
Alapesetben a Git automatikusan egyesíti a fájlokat, azonban bizonyos esetekben - például amikor ugyanazon fájl ugyanazon sorai különböző branch-eken megváltoznak - ún. konfliktus jön létre, amelyről a terminál is tájékoztat:
Ennek a feloldása igen egyszerű: minden, a konfliktusban érintett fájlban meg kell keresni azokat a részeket, amelyek nem egyesíthetőek automatikusan és kézzel (azaz a fájl megnyitásával és szerkesztésével) a végleges verziót kell meghagyni. Ezt követően a változtatást ismét commit-álhatjuk. A konfliktust a Git <<<<<<<, =======, és >>>>>>> jelzésekkel látja el.
Terminálban a git branch-ek és commit-ok ''vizualizálhatóak''
git log --graph --oneline --decorate --all
Változtatások lehúzása¶
Előfordulhat, hogy egy másik fejlesztő a saját számítógépén szintén dolgozik a local repository-ban, amit aztán közzétesz a remote repository-ban is. Értelemszerűen erről a változtatásról mi semmit nem tudunk egészen addig, amíg a saját local repository-nkat nem akarjuk közzétenni. Nézzük meg ilyenkor mi történik, feltételezve, hogy a másik fejlesztő változtatása már elérhető a távoli tárolóban.
Látható, hogy a master branch-en módosított fájlt nem tudjuk felküldeni a remote repository-ba, mivel valaki (a másik fejlesztő) minket megelőzve már feltöltött egy változtatást. Így tehát először ezt a változtatást kell letölteni a következő utasítással:
git pull
A másik fejlesztő által módosított fájl azonban ismét egy konflikushelyzetet hozott létre, így először azt kell feloldanunk.
Végezetül ha GitLab-ra tekintünk, akkor az összes commit, amit a 2 branch-en létrehoztunk, illetve a másik fejlesztő commit-ja is elérhető a remote repository-ban:
Egyéb hasznos funkciók¶
További lehetőségek repository létrehozására (git init): https://www.atlassian.com/git/tutorials/setting-up-a-repository
További lehetőség változtatások visszavonására és az ún. detached HEAD-ről: https://www.atlassian.com/git/tutorials/undoing-changes
git pull = git fetch + git merge: https://www.atlassian.com/git/tutorials/syncing/git-fetch
git stash: https://www.atlassian.com/git/tutorials/saving-changes/git-stash
git rebase: https://www.atlassian.com/git/tutorials/merging-vs-rebasing
git diff: https://www.atlassian.com/git/tutorials/saving-changes/git-diff
git stash: https://www.atlassian.com/git/tutorials/saving-changes/git-stash
Fork: https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html
Merge request: https://docs.gitlab.com/ee/user/project/merge_requests/
Összefoglaló¶
Hogyan és mit (ne) tároljunk¶
Formailag a fájlok elhelyezkedése a Git tárolóban nem különbözik egy általános mappastruktúrától, így elvárt, hogy a fájlok rendszerbe szervezett, logikus módon legyenek tárolva. Egy ilyen struktúrát ír le a következő ábra:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Ahogy azt már az előző anyagrészben is tárgyaltuk, a Git verziókezelő rendszer a szöveges állományok, így tipikusan a forráskód fájlok, dokumentációk változáskezelésében hatékony. Így tehát bizonyos fájloknak a feltöltését meg akarjuk akadályozni. Erre lesz jó az ún. .gitignore fájl, amelyben fel tudjuk sorolni mindazon fájlokat, amelyeket figyelmen kívül szeretnénk hagyni.
Ezt a .gitignore fájlt tipikusan a projektünk gyökerébe helyezzük el. Ilyen fájt automatikusan is tudunk generálni, amellyel pillanatok alatt létrehozatjuk a fejlesztői környezethez és az adott programozási nyelvhez tartozó .gitignore fájlt: https://www.toptal.com/developers/gitignore
Automatikus elemzés¶
A félév során minden projekt mester branch-ét egy automatikus szoftver fogja elemezni.
Ehhez szükséges a következők következetes használata:
git config --global user.name „Teszt Elek"
git config --global user.email „h123456@stud.u-szeged.hu
Azonban ha elfelejtük átírni, akkor az automatikus elemzés hibásan jelenik meg (hiszen minden különböző konfigbeállítást új felhasználónak tekint).
Amennyiben kiadjuk a következő utasítást, láthatjuk hány különböző konfigbeállítással használtuk a tárolót (azaz láthatjuk az összes felhasználót, aki legalább egyszer már commit-olt):
git shortlog –se
Lehetőség van szerencsére összevonni a statisztikai elemzést, amennyiben a projekt gyökerében hozzatok létre egy .mailmap fájlt, és az előző utasítás kimenetét felhasználva a következő formátumra hozzuk:
NEV <email> HELYETTESITENDONEV <helyettesitendoemail>