Verziókövető rendszerek

Áttekintés

Mi történik a kóddal, ha a fejlesztő leprogramozta? Elvileg elkészíti a futtatható, elküldi annak, akinek készítette, és nincs rá többé szükség. A gyakorlatban később is hozzá kell nyúlni: kisebb-nagyobb fejlesztéseket végrehajtani, hibákat javítani, vagy épp átstrukturálni, mindenféle funkcionális változás nélkül. A legtöbb esetben nem is egy ember fejleszti, hanem több, ráadásul a fejlesztők összetétel idővel is változik.

Ha csak úgy elküldik a fejlesztők a kódot egymásnak, akkor könnyen félrecsúsznak a dolgok: véletlenül nem azt küldi el, amiből a bináris készült; van egy fejlesztés, ami még nem fejeződött be, de egy hibát gyorsan ki kellene javítani; véletlenül letörni az egyetlen másolatot stb.

Igen korán megjelent az igény a forráskód központi tárolására, ahol egyértelmű, mi az aktuális verzió, ellenőrzött körülmények között kerülhet csak be új kód, nem veszik el olyan könnyen az adat, és követni lehet a változásokat: ki mikor mit módosított. Ezeket a rendszereket hívjuk verziókövető rendszereknek (version control system). Ebből is többféle van; ebben a szakaszban néhány ilyet ismerünk meg.

Subversion

Ez az Apache projektje (https://subversion.apache.org/). Szokásos rövidítése SVN. A fejlesztőnek alapvetően a kliens oldallal érdemes megismerkednie. Ha valaki kísérletezni szeretne a szerver telepítéssel is, Windows alatt a VisualSVN programmal érdemes próbálkoznia (https://www.visualsvn.com/server/).

Többféle kliens programmal tudjuk használni. Én a TortoiseSVN-t ismerem, amit innen ingyen le tudunk tölteni: https://tortoisesvn.net/. Ez valójában a Windows context menübe épül be, azaz jobb kattintással érhetjük el. Néhány fontosabb művelet:

  • SVN Checkout: ezzel lehet letölteni a kódot. Ha kapunk egy ún. SVN repository linket, akkor azt ide kell beírni, és rekurzívan lemásolja nekünk a kód aktuális állapotát. A checkout tehát az SVN terminológiában a kód kezdeti megszerzését jelenti.
  • SVN Update: ha egy olyan könyvtáron nyitjuk meg a context menüt, ahol már megtörtént a kód letöltése, akkor a fenti lehetőséget nem látjuk, "cserébe" viszont megjelenik ez. Ennek segítségével tudjuk aktualizálni a kódot. Ha egy kolléga módosított a kódon, akkor így tudjuk elérni azt, hogy nálunk is a legfrissebb látszódjon.
  • SVN Commit…: a mi módosításainkat tudjuk ezzel publikálni úgy, hogy mások is lássák. Ez esetben természetesen őnekik is végre kell hajtani az SVN Update műveletet. A commit során megadhatunk egy megjegyzést, amit illik rendesen kitölteni, hogy később pontosabban tudjuk, miről is volt szó a módosításban.
  • TortoiseSVN → Branch/tag…: ha alapból létrehozunk egy verziót, annak a (tipikus) neve trunk. Ezen vannak a legfrissebb fejlesztések. Előfordulhat több termékvonal, pl. több verziót kell támogatni párhuzamosan; ez esetben tudunk ágakat, azaz branch-eket létrehozni. Egy-egy ilyen ág neve tipikusan branch/[verzió]. Itt a verzió általában 2 számjegyből áll (branch/x.y). Ha egy verziót szeretnénk létrehozni (nem feltétlenül készítünk verziót minden köztes módosításból), akkor azt mondjuk, hogy "magtegeljük". Technikailag ugyanazt a műveletet jelenti, mint a branch esetén, két ponton viszont a szokás eltér: egyrészt itt általában nem 2, hanem 3 szemjegy szerepel a verzióban (tag/x.y.z), másrészt ezt később nem módosítjuk.
  • TortoiseSVN → Merge…: az egyik ág módosításait be tudjuk automatikusan "önteni" egy másik ágba. Tipikusan erre akkor van szükség, ha több verziót kell támogatni, és egy régebbi verzióban előjön egy hiba, amit kijavítunk. Mivel az újabb verziók általában felülről kompatibilisek a korábbiakkal, ugyanaz a hiba jó eséllyel az újban is benne van. Ez a művelet megpróbálja a változtatásokat automatikusan átültetni. Ez annyiban több annál, hogy ugyanazt a változást végrehajtjuk a másik ágon is, hogy itt elmenti azt a műveletet is, hogy honnan hova történt a kód átültetése, amit grafikusan meg lehet jeleníteni. Ez az információ hasznos lehet a későbbiekben.
  • TortoiseSVN → Get lock…: alapból bárki módosíthatja a kódot. Ezzel kizárólagosságot kérhetünk magunknak. Különösen bináris fájlok esetén lehet hasznos, ahol nem lehetséges két verzió összefésülése. Párja a Release lock….
  • TortoiseSVN → Revision graph: kirajzolja a módosításokat. Ezzel lehet követni, hogy hogyan változott a kód, milyen ágak jöttek létre és honnan stb.
  • TortoiseSVN → Check for modifications: ahogy a neve is mondja, az általunk végrehajtott módosításokat jeleníti meg. Ezzel tudjuk ellenőrizni, hogy mit módosítottunk, mielőtt beküldjük. Különösen hasznos akkor, ha meg szeretnénk mutatni a kollégáinknak.
  • TortoiseSVN → Revert…: a módosítások elvetése.
  • TortoiseSVN → Clean up…: ha egy művelet sikertelen, akkor a rendszer inkonzisztens állapotba kerülhet. Ez esetben jól jöhet ez a lehetőség, amely megpróbálja megtisztítani a rendszert.
  • TortoiseSVN → Resolve…: párhuzamos fejlesztések során a rendszer megpróbálja összefésülni a módosításokat. Ha az egyik fejlesztő csak az egyik függvényt módosította, a másik meg csak a másikat, akkor ezt könnyen meg tudja tenni. Azonban előfordulhat olyan is, hogy ugyanazt a kódrészletet érintette kettő vagy több fejlesztő, és nem tudja automatikusan összefésülni. Ez esetben ún. "merge conflict" állapotba kerül a rendszer. Ennek segítségével tudjuk ezeket feloldani.

Az integrált fejlesztőeszközöknek is vannak SVN beépülőik; közvetlenül onnan is végre tudjuk hajtani az SVN műveleteket (bár én jobban szeretem külön).

Az SVN még sok egyéb műveletet tartalmaz; ennek a leírásnak nem célja a lehetőségek részletes ismertetése.

Git

Áttekintés

A git filozófiája eltér a korábbiaktól, pl. az imént bemutatott SVN-től. Sokkal komplikáltabb, a betanulási görbe is hosszabb, de a lehetőségek is kibővülnek. Mivel összetettebb rendszerről van szó, külön alfejezetekben foglalkozunk az egyes lehetőségekkel.

Természetesen ez is a szoftver forrásának tárolására használatos, az alap célja tehát ugyanaz, mint mondjuk az SVN-é. Néhány lényeges különbség:

  • Az git elosztott. Ez technikailag azt is jelenti, hogy helyileg meg van a teljes verziótörténet (ellenben az SVN-nel, ahol korábbi verziókért a szerverhez kell fordulnunk).
  • Az előző pontból következik (bár a gyakorlatban atipikus) az, hogy egy-egy fejlesztői gép szerverként is funkcionálhat. Az viszont mindenképpen következik, hogy ha a központi szerver meghibásodik, az adatok nem vesznek el, mert ott vannak a fejlesztői gépeken.
  • Az SVN-ben a branch egy nehéz fajsúlyú valami: a fő verziókra hozzuk létre őket, sok esetben külön jogosultság is kell hozzá, ill. tag-eket is csak ritkán használunk, új verzió esetén. Ellenben a git-ben a branch egy hétköznapi dolog; a fejlesztők tipikusan minden módosításhoz létrehoznak egyet.
  • A gitet - összetettsége okán - általában parancssorból használjuk (az SVN-nel ellentétben, amit szinte kizárólag grafikus felületen).
  • A git alkalmas nagy méretű projektek kezelésére, melyben sok fejlesztő vesz részt. Az SVN csak párfős projekt menedzselésére alkalmas hatékonyan.

Beállítások

Töltsük le és telepítsük fel a klienst a https://git-scm.com/ oldalról. A következő (opcionális) parancsokkal beállíthatunk pár paramétert:

git config --global user.name "Farago Csaba"
git config --global user.email hu.faragocsaba@gmail.com

Repository kezelés

Repository-t alapvetően kétféleképpen tudunk létrehozni. Üres reporitory létrehozésa:

git init

Ez a kevésbé tipikus. Gyakoribb az, hogy már egy létező repository tartalmát töltjük le:

git clone https://github.com/faragocsaba/java.git

Ebben a példában a GitHub oldalról klónozunk egy repository-t; erről még lesz szó bóvebben később.

Tartalom módosítása

A tartalom módosításával kapcsolatos legfontosabb parancsok az alábbiak. Tegyük fel, hogy módosítottunk a tartalmon valamilyen fejlesztőeszközzel.

A módosított fájlok áttekintése

git status

Ez a parancs felsorolja, hogy mely fájlokat adtuk hozzá, melyeket módosítottuk, melyeket töröltük, és melyeket neveztük át. A git kellően intelligens ahhoz, hogy ha egy törölt és egy létrehozott fájl tartalma ugyanaz, vagy nagyon hasonló, akkor azt átnevezésként kezelje. Más rendszerekben van egy átnevezés beépített művelet; ott nem elég fájlrendszer szinten átnevezni.

Ezen kívül azt is jelzi, hogy mely fájlokat jelöltük meg a következő commithoz (ld. lejjebb): azokat zölddel jeleníti meg, a többit pirossal.

A módosítások részletei

git diff

Ezzel azt tudjuk megnézni, hogy egész pontosan mely sorok változtak. Színesen jeleníti meg, pirossal jelölve a törölt és zölddel a hozzáadott sorokat. A módosítást itt egy törléssel és egy hozzáadással modellezi.

Egy konkrét fájl módosításai:

git diff README.md

A módosítások előkészítése beküldésre

git add .

Ezzel a paranccsal minden módosítást hozzáadunk a következő commithoz. Ez még nem a commit maga! Ha módisítunk rajta commit előtt, akkor azt is hozzáadhatjuk később. Ha nem szeretnénk sz összes módosított fájlt hozzáadni (pl. az IDE által generált fájlokat célszerű kihagyni; erről még később lesz szó részletesen), akkor a fájlokat egyesével is megadhatjuk:

git add README.md

A git status parancsot ismét kiadva zölddel jeleníti meg a hozzáadott fájlokat. Megjegyzés: ha nem történt változtatás, akkor nem lehet hozzáadni a commithoz.

A beküldésre előkészített fájl visszavonása

git reset HEAD .

Ezzel visszavonjuk az összes előkészített fájlt. Itt is megadhatjuk egyesével is:

git reset HEAD README.md

Módosítások visszavonása

Ha az összes módosítást, mait végrehajtottunk, vissza szeretnénk vonni, azt a következő paranccsal tudjuk megtenni:

git checkout .

Előtte vissza kell vonni a commitra való előkészítést is. Egy fájlra is működik:

git checkout README.md

Ez nem törli ki az új fájlokat, csak a módosításokat (és törléseket) vonja vissza. Ennek a parancsnak nem ez az elsődleges funkciója, inkább csak mellékhatása; később még lesz zsó róla bővebben.

Módosítások véglegesítése lokálisan

A commit paranccsal tudjuk az előkészített fájlokat véglegesíteni:

git commit -m "Minor update for checking the commit command."

Commit visszavonása

Elvileg a git reset paranccsal lehet visszavonni egy commitot. Meg kell adni a legutóbbi verzió hosszú azonosítóját, amit a git log paranccsal tudunk meg. Nálam nem igazán működött ez a módszer; a legegyszerűbb letörölni és újra klónozni.

Commit beküldése

Ezen a ponton még nem küldtük be a távoli szerverre a módosításokat. Ezt a következő paranccsal tudjuk megtenni:

git push

gitignore

Vannak bizonyos könyvtárak és fájlok, amelyeket nem célszerű commitolni. Ilyen pl. a target könyvtár, vagy az IDE által generált, a lokális beállításokat tartalmazó fájlok. Ezt megoldhatjuk úgy is, hogy minden git add parancsnál egyesével megadjuk a commitolni kívánt fájlokat, de sokkal egyszerűbb felsorolni, hogy mit nem szerenénk soha commitolni. Ehhez hozzunk létre egy fájlt .gitignore néven (ld. a bevezető pontot) a gyökérben, és ott soroljuk fel a megfelelő fájl- és könyvtárneveket. Ezt a fájlt is commitolni kell.

Pl. ha Eclipse-t és Mavent használunk, akkor a következő lehet a fájl tartalma:

# Maven 
target/

# eclipse project file
.settings/
.classpath
.project

Branch-ek kezelése

Amint arról volt szó, a branch-ek készítése git-ben alapvető. Branch készítése:

git checkout -b mybranch

ahol a mybranch a branch neve. Ez automatikusan a kiválasztott branch-re vált. A fő branch a master; arra a következőképpen tudunk visszaváltani:

git checkout master

Ill. tetszőleges branch-re ilyen módon válthatunk. Ha az egyik branch-en módosítjuk a kódot, majd végrehajtjuk a commitot, és branchet váltunk, akkor a módosítást nem látjuk. Ha visszaváltunk az eredeti branchre, akkor ismét látjuk.

Felhívom a figyelmet a checkout fogalmának eltérő voltára itt és a többi verziókövető rendszeren, pl. az SVN-en. Az SVN-en a checkout a kód letöltését jelenti, itt branch váltást. Ill. - ahogy fent láttuk - mellékhatásként használható a módosítások visszavonására is.

A branch-ek hierarchiába szervezhetőek. Adott nem master branch-ből készíthetünk másik branch-et, tetszőleges számút. Az alábbi példában a master branch-ről készítettük a branch1-et, és azon belül ugyanazon a ponton ágazik el a branch2 és a branch3.

              K - L - M branch3
             /
            / H - I - J branch2
           / /
      E - F -- G branch1
     /
A - B - C - D master

A branch-ek kilistázása:

git branch

A távoli branch-ek megjelenítése:

git branch -a

Elképzelhető, hogy van olyan távoli branch, ami lokálisan nem létezik. Távoli branch-k letöltése (verziótörténettel):

git fetch

Távoli branch-ek checkout-olása ugyanúgy történik, mint a lokálisé, viszont a névből töröljük le a remotes/origin/ prefixet. Tehát ha a branch neve mondjuk remotes/origin/apple, akkor a szükséges művelet: git checkout apple.

Ha a branch-et lokálisan hoztuk létre, és módosítást hajtottunk végre, akkor először a git push nem elég; a következőt kell végrehajtani:

git push --set-upstream origin mybranch

Ha a távoli branch volt előbb, akkor erre nincs szükség.

Ha egy branch tartalmát bele szeretnénk tenni egy másikba, akkor a cél ágba lépjük bele (pl. git checkout master), majd adjuk ki a következő parancsot:

git merge mybranch

Ennek az eredménye a következő lehet:

      E - F - G mybranch
     /         \
A - B - C - D - H - I master

A példában párhuzamosan fejlődött a master és a mybranch, és a H pontban került bele ugyanabba a verzióba mindkét változat.

Branch törlése:

git branch -d mybranch

Ez csak akkor működik, ha nem az adott branchben állunk, és már megtörtént a merge. Ha nem szeretnénk merge-elni, akkor a következőképpen tudjuk törölni:

git branch -D mybranch

Ha lokálisan töröltük a branch-et, az még a távoli szerveren megmarad. Ha onnen is törölni szeretnénk, akkor a következő paranccsal tudjuk megtenni (miután lokálisan megtettük):

git push origin --delete mybranch

A branchek törlése - amint látni fogjuk - a létrehozásához hasonlóan napi rutin. Ha a fenti példában nem törölnénk a mybranch-et, akkor az I időpillanatban is még létezne, akár tudnánk módosítani. A tartalma a G lenne, tehát a merge előtti, és később akár ismét tudnánk merge-elni:

      E - F - G - J mybranch
     /         \   \
A - B - C - D - H - I master

A valóságban ezt általában nem szeretnénk, emiatt töröljük. A törlés nem azt jelenti, hogy a branch végleg elveszett, csak azt, hogy az aktuális időpillanatban nem látszik. A teljes verziótörténet benne marad a rendszerben, így ha kilistázzuk a történetét, akkor az ott lesz a megfelelő helyen, a törlés után is.

A verziótörténet kilistázása

A következő paranccsal tudjuk kilistázni a változtatásokat:

git log

A valóságban nagyon sok változtatás van, ami áttekinthetetlenné teszi a verziótörténetet. Paraméterekkel lehet finomhangolni a kiírást, melyről részletesen a specifikációban olvashatunk: https://git-scm.com/docs/git-log.

Merge conflict

Az előző szakaszban említettük a git merge utasítást. Előfordulhat, hogy nem tudja automatikusan feloldani az eltéréseket; ekkor merge conflict állapot lép fel. A feloldását akármilyen szövegszerkesztővel kézzel tudjuk megtenni:

  • A git status utasítás megjeleníti azokat a fájlokat, amelyek konfliktus állapotban vannak.
  • A jelzett fájlokban <<<<<<< és >>>>>>> között találjuk a kérdéses sorokat.
  • Tetszőleges szövegszerkesztővel oldjuk fel az összes konfliktusos állapotot.
  • Hajtsunk végre git add és git commit utasításokat.

Távoli módosítások letöltése

Amint arról már szó volt, a git fetch utasítással tölthetjük le a távoli branch-eket. A git checkout parancsot alkalmazhatjuk ilyen branch esetén is, a fent említett prefixet ki kell törölni.

Ha egy branch-en többen dolgozunk, és a kollégánk módosított rajta valamit akkor (az adott branch-ben állva) a következő paranccsal tudjuk letölteni a változtatásokat:

git pull

Távoli git repository kezelése

Már volt példa arra, hogy hogyan módosítsunk a távoli repository tartalmán. A git remote paranccsal tudunk finomhangolt távoli parancsokat kiadni. A https://git-scm.com/docs/git-remote oldal felsorolja a lehetőségeket.

Release készítése

Időnként verziót hozunk létre a forrásból, és ezt célszerű a verziókezelő szintjén is jelezni. Ehhez a git tag parancsot használhatjuk, pl. az 1.0.0 verzió létrehozásához:

git tag 1.0.0 <commitID>

A commitID-t legegyszerűbben a git log parancs segítségével tudjuk lekérdezni.

Rebase

Tegyük fel, hogy készítettünk egy branch-et, és azon dolgoztunk, de közben azon a branch-en is dolgoztunk, amiből származtattunk. Azt szeretnénk elérni, hogy az alap branch változtatásai belekerüljenek az új branch-be, és úgy szeretnénk látni, mintha a legfrissebb verzióról történne a branch létrehozása. Például ez az aktuális állapot:

          G - H - I mybranch
         /
A - B - C - D - E - F master

És ezt szeretnénk elérni:

                      G' - H' - I' mybranch
                     /
A - B - C - D - E - F master

ahol az aposztrof azt jelenti, hogy a D, E és F módosítások is benne vannak. Ezt a következőképpen tudjuk elérni:

git checkout mybranch
git rebase master

vagy ami ezzel ekvivalens:

git rebase master mybranch

Mivel itt a git megpróbálja összefésülni a módosításokat, előfordulhat, hogy ezt nem tudja megtenni automatikusan, merge conflict adódik. A fent bemutatott módon tudjuk ezt feloldani.

TortoiseGit

Az eddigiekben csak parancssoros műveleteket láttunk. Valójában parancssorral minden megoldható, sőt, elsősorban ez a javasolt. Ugyanakkor vannak grafikus kliensek is, ahol kényelmesebben tudjuk végrehajtani a git műveleteket. Az egyik a ToroiseGit, ami a TortoiseSVN mintájára a context menübe épül be. Letöltése: https://tortoisegit.org/. Az alap műveleteket nem sorolom fel, azok adják magukat, ill. vannak műveletek, amelyeket én sem tudom, hogy mire valók. Azonban van két olyan művelet, amellyel mindenképpen érdemes megismerkednünk:

  • Revision graph: ez a branch-ek struktúráját mutatja be, grafikus formában. Így sokkal áttekinthetőbb, mint kibogarászni a git log parancs eredményéből.
  • Repo-browser: itt a részletes commitokat láthatjuk, grafikus formában. Ennek is az alapja a git log.

Sourcetree

A másik népszerű grafikus felület a Sourcetree, amit a https://www.sourcetreeapp.com/ oldalról tudunk letölteni. Ez egy önálló alkalmazás, és a központi eleme a verziótörténet vizuális ábrázolása, ezt láthatjuk a főoldalon. Például a törölt branch-ek is a helyükön vannak: láthatjuk hogy mikor jöttek létre és hol történt a merge, ahol meg is szűnt. Részletesen látjuk azt is, hogy ki mikor és mit commitolt. Az alap műveleteket ennek segítségével is végre tudjuk hajtani.

GitHub

A https://github.com/ egy (magán célra) ingyenesen használható git rendszer. Ott létre tudunk repository-kat hozni, és központi szerverként használni. Amióta megvette a Microsoft, igen nehézkessé vált a használata. Lássuk!

  • Telepítsük a git-et, ha még nem tettük meg (https://git-scm.com/.
  • Regisztráljunk a https://github.com/ oldalon. Készüljünk fel arra, hogy nem fogjuk tudni használni a szokásos jelszavunkat. Az én azonosítóm faragocsaba.
  • Lépjünk be.
  • Készítsünk egy új repository-t. A képernyő bal felső sarkában kattintsunk a New gombra.
  • A repository neve elvileg bármi lehet, pl. myproject.
  • A kódot klónoznunk kell lokálisan. Ezt többféleképpen is megtehetjük, melyhez segítséget ad a weboldal. Egyik lehetőség:
git clone https://github.com/faragocsaba/myproject.git
cd faragocsaba.github.io

A használatához tokent kell létrehoznunk:

  • A jobb felső sarokban kattintsunk az ikonunk melletti kis lefelé mutató háromszögre → Settings → Developer Settings → Personal access tokens
  • Generate new token
  • Adjunk neki egy tetszőleges nevet
  • Válasszuk ki a scope-okat. A repo mindenképp legyen bekapcsolva; én bekapcsoltam még az admin:repo_hook-ot, a gist-et és a delete_repo-t is.
  • Generate token
  • Másoljuk a vágólapra a generált tokent. (Ezt explicit meg kell tennünk, a mellette levő kis ikon nem működik.)

Egy másik módszer az SSH token használata.

A GitHub részletes ismertetése meghaladja a leírás kereteit, de pár fontosabb funkciót megemlítek:

  • A Code fülön láthatjuk magát a kódot. Lényegében ez a legfontosabb része a rendszernek. Itt tudunk branch-et létrehozni (kissé nehézkesen vehető észre: kattintsunk a master melletti lefele mutató nyílra, majd kezdjük el írni; felkínálja), a kódot böngészni, fájlt hozzáadni, a kódot letölteni (ld. a Code alatti lehetőségeket).
  • Az Issues fülön egy egyszerűbb issue tracking rendszert láthatunk.
  • A Pull requests fül lényegében a kód review fül: több fejlesztő esetén ha egy változtatást saját branch-en készítettünk, akkor mielőtt a fő branch-re másolnánk azokat, itt tudunk megkérni másokat arra, hogy nézzék át a kódunkat.

A többi kevésbé fontos.

BitBucket

Amennyiben mi magunk szeretnénk üzemeltetni egy git rendszert (pl. külső szerverre nem kerülhet a kód), akkor ajánlott a BitBucket, amit a https://bitbucket.org/ oldalról tudunk letölteni. Jó kezelhető grafikus felülete van, ahol a repository-kat projektekbe tudjuk szervezni, itt is meg tudjuk nézni a verziótörténetet grafikusan, valamint pull requesteket is létre tudunk hozni. Ez utóbbit egy egyszerű code review eszköz is támogat.

Gitflow

Eddig csak arról volt szó, hogy hogyan kell egyes műveleteket végrehajtani, arról viszont nem, hogy hogyan érdemes. A Gitflow egy népszerű, kvázi szabványos branching modell, amit érdemes megtanulni és követni. Szabályok:

  • Azonnal létre kell hozni egy develop branch-et a master-ből. Ezt a branch-et soha nem töröljük le.
  • Közvetlenül viszont sem a develop-on, sem a master-en nem dolgozunk, egy dolgot kivéve: a develop-on a megfelelő hely(ek)re beírjuk a SNAPSHOT verziót. Ha a következő verzió mondjuk az 1.3 lesz, akkor ide a következőt írjuk be: 1.3-SNAPSHOT. Az elején általában a 0.1-SNAPSHOT-ot szokás megadni.
  • Ha bármit módosítani kell, akkor arra megfelelő branch-et hozunk létre a develop branch-ből. Ezeknek megvan a maguk elnevezési konvenciója:
    • Feature fejlesztés esetén: feature/[ticketszám]-[megnevezés], pl. feature/MYPROJ-123-user-handling
    • Hibajavítás esetén: bugfix/[ticketszám]-[megnevezés], pl. bugfix/MYPROJ-156-invalid-input-check
  • Ideiglenesen feltölthetjük a változtatásokat a központi szerverre, különösen akkor, ha többen dolgoznak ugyanazon a problémán.
  • A develop branch-re történő merge-et meg kell, hogy előzze egy code review. Az egyes git rendszerek (BitBucket, GitHub) általában tartalmaznak ilyen mechanizmust. Ez ún. pull request létrehozásával kezdődik, ahol megadjuk, hogy pontosan melyik branch-ről melyik branch-re szeretnénk belefésülni az adatokat.
  • A merge csak jóváhagyás után történhet meg. Ha módosítani kell a kódon, akkor azt a feature vagy bugfix branch-en tesszük. A pull request továbbra is megmarad, és ha történik commit a feature branch-en, és utána merge-elünk, akkor az új változtatások is benne lesznek.
  • Merge után azonnal törölni kell a feature vagy bugfix branch-et. Ezt általában a git rendszerek automatikusan felkínálják.
  • Tetszőleges számú feature fejlesztés vagy bugfix történhet párhuzamosan.
  • Az adott branchen történő változtatás kizárólag az arra a jegyre (ticketre) vonatkozhat, amire hivatkozik.
    • Jegy nélkül semmilyen változtatás nem megengedett.
    • Olyat nem szabad csinálni, hogy egy feature fejlesztés során mellesleg kijavítunk néhány hibát, refaktoráljuk a kódot, és optimalizálunk is. Ezeket a tevékenységeket szükség esetén természetesen végre kell hajtani, de mindegyikhez külön jegyet kell létrehozni.
    • Utólag tehát pontosan visszakereshető lesz az, hogy melyik módosítás pontosan mi volt és mi miatt történt, és fordítva, egy adott jegynek mi lett a hatása a kódra. A modern jegykezelő rendszerek általában összekapcsolhatóak a gittel (ill. más verziókövető rendszerekkel), így a jegykezelő rendszer → verziókövető rendszer irány is működik. Javasolt jegykezelő rendszer a git-het: Jira.
  • Produkciós verziót soha nem készítünk feature vagy bugfix branch-ről, és a develop branch-ről sem, valamint a develop-ról soha nem merge-elünk a master-re. A verzió lépései az alábbiak:
    • Meggyőződünk arról, hogy az összes feature fejlesztés vagy bugfix, amit bele szeretnénk tenni a verzióban, benne van.
    • A develop branch-ből létrehozunk egy release branch-et, release/[verzió] néven, pl. release/1.3.
    • A release branch-en kizárólag a verziószámot módosítjuk, mégpedig úgy, hogy a -SNAPSHOT postfix lekerül. Ha tehát 1.3-SNAPSHOT volt a verzió, akkor azt 1.3-ra változtatjuk. Semmi más módosítás a release branch-en nem megengedett, ez viszont kötelező.
    • Release után annak tartalmát két helyre merge-eljük: az egyik a master, a másik pedig a develop. Merge conflict elméletileg nem fordulhat elő.
    • Ezt követően a develop-ra beírjuk a következő verziót, pl. 1.4-SNAPSHOT.
  • Ha a release után kibukik egy olyan hiba, amit azonnal javítani kell, nem várhatunk a következő verzióig, akkor arra ún. hotfixet kell kiadnunk, melynek menete a következő:
    • A master branch-ből, ami a frissen merge-elt módosításokat tartalmazza, készítünk egy hotfix branch-et, hotfix/[ticketszám]-[megnevezés] néven, pl. hotfix/MYPROJ-182-npe-fix.
    • Végrehajtjuk a módosítást, és a szokásos módon (ill. annál is körültekintőbben) commitoljuk. Megfelelő alverziót módosítunk, pl. 1.3.1.
    • A módosításokat merge-eljük a master és a develop branch-ekre.

Részletes leírások erről a módszerről:

Az alábbi ábra (forrás: a fenti második link) egy jó áttekintést nyújt erről a módszerről:

gitflow.png

Források

Az alábbi leírások kiváló áttekintést nyújtanak erről a rendszerről:

További verziókövető rendszerek

A fenti két verziókövető rendszer két filozófiai megközelítést valósít meg, és mindkettő népszerű a maga nemében. Azonban számos egyéb ilyen rendszer van, melyek közül említés szintjén felsorolok párat:

  • CVS: az első között jelent meg a kategóriában. Ma már muzeális darab.
  • ClearCase: elég komplikált, fizetős rendszer; az írás pillanatában már leáldozóban van a csillaga.
  • SourceSafe: a Microsoft fizetős rendszere, melynek tudása nagyjából az SVN-nek felel meg.
  • AccuRev: nehézkes, ráadásul fizetős.
  • Mercurial: a git valós alternatívájának tekinthető. Nincs benne tapasztalatom.

Egy teljesebb listát a https://en.wikipedia.org/wiki/List_of_version-control_software oldalon találunk.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License