Warning: Creating default object from empty value in /chroot/home/zerotohe/zerotohero.hu/html/wp-content/themes/salient/nectar/redux-framework/ReduxCore/inc/class.redux_filesystem.php on line 29
merge with conflict | zeroToHero

merge with conflict

By 2015.01.14Git

Sziasztok!

Legutóbb a git témakörön belül a branchekről beszéltünk, megnéztük mik ezek, és hogyan használhatóak. Ám elcsaltam egy fontos részt a felmerülő problémákat illetően. Milyen problémára gondolok? Amikor csapatban dolgozol, akkor valójában elég ritka lesz az az eset, amikor a branch-ek mergelése olyen egyszerű lesz, mint ahogy azt korábban bemutattam. A legtöbb esetben merge conflictjaid lesznek, amelyeket fel kell oldanod.

Kicsit olyan lehet az érzésed ezzel kapcsolatban mint, amikor valamilyen orm-et kezdesz el tanulni, és a doksiban ott a „csoda” HR séma, valamint leírják, hogy ez az orm milyen szuper, így és így tud működni ezekben a konkrét esetekben. Igenám, csak amikor hirtelen ott találod magad a sokkal komplexebb sémádban, akkor jössz rá, hogy valóban: tök jó amit leírtak, de fogalmad sincs, hogyan valósítsd meg azt a saját világodban… :) Igazából ennek az elcsalásnak több oka van, de a legfőbb az, hogy lépésről lépésre szeretnénk haladni, és befoltozni, kibővíteni a hiányosságokat az érthetőség tükrében. Tehát tök jó amit multkor leírtam, de az csak egy része az igazságnak :) Szóval most bővítsük ki az ismereteket, és nézzük meg mi történik akkor amikor olyan fájlokat kell mergelni, amelyek tartalma eltérő.

Hogyan?

Egy példán keresztül lehet igazán érzékeltetni mindazt, amit megpróbáltam szavakba önteni, igaz a példa nem lesz valami magasröptű, de hát melyik világ tökéletes? :)

Hozzunk létre egy üres repository-t, és adjunk hozzá egy fájlt:


$ git init
$ touch HelloWorld.java
$ git add HelloWorld.java
$ git commit -m „HelloWorld skeleton”

Ezután hozzunk létre két branch-et, ezeken a brancheken fogjuk módosítani a HelloWorld.java fájlt.


$ git branch feature/HelloWorld1
$ git branch feature/HelloWorld2

Ezekután implementáljuk a java fájlt:


$ git checkout feature/HelloWorld1

és legyen a HelloWorld.java tartalma az alábbi:


public class HelloWorld {
        public static void main(String[] args) {
                System.out.println(" Hello World ");
        }
}

majd commitoljuk be. Ezekután váltsunk át a feature/HelloWorld2 branch-re, és ott legyen az alábbi a HelloWorld.java tartalma a következő:


public class HelloWorld {
        public static void main(String[] args) {
                System.out.println(" Hello World!");
        }
}

Ezt is commitoljuk be, és váltsunk vissza a master branch-re. Majd a feature/HelloWorld1 – et mergeljük a masterre:


$ git merge feature/HelloWorld1
Updating 742fbc1..eb8a62c
Fast-forward
HelloWorld.java | 5 +++++
1 file changed, 5 insertions(+)
$

Ezt ugye láttuk a legutóbbi alkalommal, itt semmi extra nincs. (Ha megnézzük a HelloWorld.java tartalmát, akkor láthatjuk, hogy sikeres volt a merge.) Akkor kövessük el az alábbiakat:


$ git merge feature/HelloWorld2
Auto-merging HelloWorld.java
CONFLICT (content): Merge conflict in HelloWorld.java
Automatic merge failed; fix conflicts and then commit the result.

Ez az a pont amit nekünk kell feloldani, ugyanis nem mondtunk mást a git-nek. Mielőtt folytatnánk érdemes telepítenünk a kdiff3 (http://kdiff3.sourceforge.net/) programot. Ez egy grafikus tool, ami segít nekünk a conflict-ok feloldásában.
Ha belenézünk a HelloWorld.java fájlba, akkor az alábbit láthatjuk:


$ cat HelloWorld.java 
public class HelloWorld {
        public static void main(String[] args) {
<<<<<<< HEAD
                 System.out.println(" Hello World ");
=======
                 System.out.println(" Hello World!");
>>>>>>> feature/HelloWorld2
        }
}

Szépen megjelöli, hogy mi ütközött. Ezen „borzasztóan bonyolult” példában a fájl editálásával is feloldhatjuk az ütközéseket, viszont valós helyzetben, ránézel a fájlra, és azt mondod, hogy nincs az az ‘sten :) No, ezért használunk tool-t röviden.

A következő parancs segítségével oldjuk fel az ütközéseket:


$ git mergetool # itt -t kapcsolóval meg lehet adni a difftool-t.
Merging:
HelloWorld.java
Normal merge conflict for 'HelloWorld.java':

{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (kdiff3):

Ezután üssünk entert, és ha minden jól megy az alábbi képet láthatjuk:

Az alsó részben látható a szépen magyarított üzenet, amely arra vonatkozik, hogy itt van ütközés. A felső három részben pedig a változatok láthatóak. A remote felirat jelöli azt, amit épp most ütközik a Local-lal. A menüsorban látható A, B, C ikonok segítségével válasszuk ki, hogy melyik verziót szeretnénk látni a végleges kódban. Ha elkezded nyomkodni az ABC-t :), akkor láthatod, hogy behelyettesíti a kívánt verziókat. Miután kiszórakoztuk magunkat a gombok nyomogatásával, válasszuk a C verziót, majd mentsük le, és zárjuk be az alkalmazást. Ezután nézzünk bele a fájlba, hátha a holdegyüttállás miatt elromlott valami:


$ cat HelloWorld.java
public class HelloWorld {
        public static void main(String[] args) {
                System.out.println(" Hello World!");
        }
}
$

Mivel számomra úgy tűnik, hogy minden rendben, ezért kész is vagyunk, commitoljunk, és legyünk vidámak, hogy a következő alkalommal, amikor sok conflictunk lesz, neadj’sten xml-eleket kell mergelnünk, akkor azt nem kézzel kell csinálnunk.

A végére egy szimpatikus kis parancs, amivel megnézhetjük, hogy mi történt a repository-nkal:


$ git log --all --graph