Git kérdések

Fórumok

Sziasztok!

Fejlesztőkörnyezet verzióváltása miatt kénytelen leszek átváltani a Git verziókövető rendszerre (eddig VSS-t használtunk), viszont ez még teljesen új terület számomra, így elég sok kérdésem volna ezzel kapcsolatban.

Tudom, hogy egy projekthez van lokális és van megosztott repo. A commit a lokális repoba teszi a változsokat, a push a lokális repóból a megosztottba.

1. Jól értelmezem, megosztott repóban levő állományok listáját csak úgy tudom lekérdezni, hogy azokat lehúzom a lokális repóba? A lokális repó listázható az ls-files paranccsal, de ugyanezt hiányolom a megosztottra.

2. Ha olyan állományt módosítok, ami közben megváltozott, mert más fejlesztő is hozzányúlt, milyen hatékonyságú az összefűzése? Ha ugyanolyan minőségben tudja összefűzni, mint az általam eddig látott összehasonlító programok mutatják az eltéréseket, akkor agyhalál lesz megtalálni, mit kutyult össze a kódban...

3. Egy módosítás egyszerűsített ciklusa a fejemben a következő:
   1. Lehúzom a megosztott repóból a legfrissebb verziót
   2. Elvégzem a szükséges módosításokat
   3. Commit-al berakom a lokál repóba
   4. Push-al felteszem a közösbe.
   Mivel időközben másik fejlesztő módosíthatott az állományokon, ezért kell egy lépés a 3. pont után, amiben ismételten lehúzom a közös repóból a változásokat, ez elvégzi a változások összefűzését.
   Az itt felmerült kérdésem: mi történik, ha a 4. lépés előtt történik a közös repóban egy változás?

4. Van-e arra mód, hogy a commit előtt lekérdezzem, hogy mely állományok változtak meg a lokál repóhoz képest?

5. Van-e arra mód, hogy megnézzem a módosult állomány és a repóban levő változat különbségét? Ugyanez a kérdés áll két commitolt változat közötti eltérésre is.

Gábor

Hozzászólások

Szerkesztve: 2025. 01. 07., k – 08:53

Szerintem lépj egyet vissza, és nézd meg eleve a git architektúráját, mert ott nincs megosztott meg lokális repo, meg hasonlok, utána elolvasol valami git for beginners doksit, és a kérdéseid nagyrésze megválaszolásra kerül.

Nincs hova visszalépni. Pont ezeket csinálom és eddig nem találtam egyértelmű válaszokat a kérdéseimre, azért tettem fel.

Lehet, hogy rossz szakszavakat használtam, lokális repo-nak neveztem azt a tárolót, ahova a commit teszi be a változásokat és megosztott reponak hívtam, ahova a push tolja át.

1. Alapvetően igen, úgy todod nézegetni a gitet, ha klónoztad. (Elvben a protokoll lehet hogy tud távoli listázást, de senki se tudja hogy.) De szokás a központi gitre valami webes megjelenítőt tenni, pl gitlabot, és akkor rá tudsz nézni mi van ott.

2. a gitnek van beépített mergje, be lehet konfolni külső toolt és az automerge le is tiltható. Akkor kézzel kell merge-ölni. Csodák nincsenek.

3. push előtt pullolsz. Ha konflikt van kézzel mergelsz ha nincs, akkor örülsz.

4. Van, a kiindulási kommit és a master diffjét meg tudod nézni gitlabon (pl) vagy lokálban pull után. Pl: git difftool -d kozoskommitazonosito integration

5. git difftool -d . parancs mutatja a hozzáadatlan változásokat. git difftool -d kommitid . pedig egy kommithoz képest az összes diffet.

1000 féle stratégia szerint lehet használni. A csapaton belüli pullreq szerintem hülyeség, arról beszéld le aki felhozza ötletként.

A csapaton belüli pullreq szerintem hülyeség, arról beszéld le aki felhozza ötletként.

Azért ez erősen függ a csapat méretétől, összetételétől, tapasztalati szintjétől és attól, hogy mennyire fegyelmezetten kezelik a requesteket. :) Valóban lassítja a fejlesztést (főleg az elején), ha minden apró módosításhoz request (és approval) kell, de a folyamatba így beépített code review hasznos tud lenni, főleg egy nagyobb/vegyes tudású csapat esetén. (Tudom, nem szükséges a pull/merge request a code review-hoz, de azért mégsem rossz alapelv, hogy próbáljuk meg eleve nem beengedni a "szuboptimális kódot".) Illetve a PR-ek adnak egy szabványosított felületet a már megírt de még nem felhasznált kód megvitatására úgy, hogy az visszamenőleg is megmarad. Szerintem ez értékes infó, ha normális code review van, sokszor segíthet megérteni egy régebbi döntés hátterét.

A csapaton belüli pullreq szerintem hülyeség, arról beszéld le aki felhozza ötletként.

Ezt kifejted? Igaz, internal sehol se láttam githubot, csak gitlabot, ott meg ugye merge request van, de az szerintem pont elég jó arra, hogy a feature branchen levő fejlesztés review köreit meg lehessen ejteni. De igazából ugyanez van githubon is, csak ott "kretén" a nevezéktan, lehet az a pull request simán branchről is, és nyugodtan mergelheti a végén a developer is, ha jóvá van hagyva. Mi ezzel a baj, hogy jó szerinted helyette?

Ez hitvita, azért dobtam be, hogy pörögjön a topik és a hup :-).

Véleményem szerint ...

(és ha megnézel ilyen progger influencereket, akkor láthatod, hogy nem vagyok egyedül ezzel a nézetemmel, de az is igaz, hogy nem mainstream)

... a pull request és a hozzá tartozó review csak lassítja a folyamatot, illetve valószínűbbé teszi, hogy lesznek konfliktok. Egyrészt egymásra kell várni folyton, másrészt pedig kontextusváltásra kényszerít mindenkit, illetve arra, hogy ne tudjon azzal foglalkozni amit a saját feladatának érez az ember. Szerintem a mostanában sokat emlegetett gyakori fejlesztői kiégés egyik oka a pull request, (illetve a sprintelgetés, de az egy másik téma).

A pull requestet arra találták ki, amikor totál ismeretlen harmadik fél kódját kell bevenni a rendszerbe. Egy csapatmunkában ha ilyenek a kollegák, az régen rossz. Azt el tudom fogadni, hogy egy újonc az első időkben csak egy senior segítségével kommittolhasson. De ha úgy marad, hogy nem tud önállóan kommittolni, akkor jobb inkább megválni tőle és kész.

Van olyan vélemény is, hogy a continuos integrationt ássa alá, hogy mindenkinek hosszú életű branchei vannak (a pull req-nak mindenképpen ez lesz a hatása, hogy hosszabbak lesznek a feature ciklusok), és emiatt nincsen egyben tesztelve a fejlesztők egymásra hatása.

Azt, hogy ne legyen törött a main branch, az biztosítja, hogy a kommit után gyorsan lefutnak a sanity checkek (jó esetben az összes teszt), és ha eltörik, akkor a fejlesztő hamar kikalapálja, mert tudja, hogy mit változtatott, ki kell tudnia jav javítani. Nyilván mindenki törekszik rá, hogy ne törje el az integratiönt és ez egy ritka esemény lesz.

Ehhez persze be kell vállalni, hogy néha törött lesz a main: szerintem ez nem tragédia. Mert mindig van egy utolsó működő, ilyenkor arra áll mindenki és tud dolgozni. (Jó eséllyel a többség észre se veszi, mert éppen feature branch-en dolgozik.) Nyilván kellemetlen ha délután 5-kor pusholunk és törjük el a maint, mert akkor illene bennmaradni ameddig helyre nem kalapáljuk. De ez az ár kisebb mint a pull req költsége összesen, és az se zárja ki teljesen, hogy eltörjön valami.

Ha nincs pull req-zás, akkor a fejlesztő tud kommittolni percek alatt, senkire nem kell várnia. És senki nem fogja zaklatni semmivel, amikor azt akarná csinálni, ami a saját célja (aktuális sprint vállalás, stb). A lényeg, hogy az ember ne legyen kizökketve abból a munkából amire éppen koncentrál. Ezzel a legjobb a szellemi erő kihasználása.

Ha együtt kell működni valamilyen célból, akkor is ezerszer jobb, hogy pikk-pakk betolhatja mondjuk az interfészt akinek az a dolga, a másik már csinálhajta is az implit. A kimaradt egymásra várásokkal napok megspórolhatók egy olyan helyzetben, amikor többszöri interakció eredménye az előre haladás.

Mivel mindenki gyorsan tud pusholni, az esetleges egymásra hatások, törések a lehető leghamarabb kiderülnek, gyorsan lehet javítani őket.

A review-ra pedig sokkal értelmesebb nagyobb darabokban review-zni mérföldkövekre. A változások merge-je felesleges mentális terhelés, mert 1-2 sorok kedvéért be kell cache-elni fejbe a kontextust amin valaki más dolgozott, tehát jó eséllyel fogalmunk sincs, hogy mi az és mi a célja. És a legtöbb programozó nem is fogja megtenni, és valójában a lényegi dolgok átsiklanak ezeken a reviewkon emiatt. Szemben a hülyeségekkel, amikbe bele fognak kötni, hogy mi a változó neve, meg van egy fölös space valahol.

Mi "lazy review" stratégiával összegyűjtünk sok változást és egyben review-zzuk. Erre elkülönített idő van, nincs stressz. Be kell cache-elni fejbe a kontextust, de van is értelme, mert nem 1 sor miatt tesszük, hanem több változás miatt egyszerre. A review-t mérföldkövekhez kötjük, akkor csináljuk meg, mondjuk egy release-hez. A review-nak ha az az eredménye, hogy szar, akkor piros lesz a kód a review reportban és egy külön kommitban javítjuk, majd újra reviewzzuk amíg jó nem lesz.

Olyan is sokszor van, hogy egy változást követ egy másik, ami felülírja. A köztes változatokat felesleges reviewzni, a végsőt kell. Ezért a "lazy review" stratégia ezzel is spórol.

A lazy review feladatra mi csináltunk egy saját eszközt, ami rendkívül egyszerű, és a fejlesztést nem akadályozza egyáltalán, viszont garantálja, hogy végül a kód review lefedettsége 100% lesz, és minden le van okézva a reviewer(ek) által.

Hát izé. :) Tök jó gondolatok, de most nem fogok tudni hosszabban válaszolni. Szóval vannak benne azért igazságok, hogy tud némi surlódást okozni, de pl ha sokat kell context switchelni, akkor a reivew akasztás csak tünet, más munkaszervezési baj van. Mondom ezt úgy, hogy én sokat context switchelek, mert pl elég nagy tételben csak reviewzni szoktam (vagy poc kódot írni a seggük alá, vagy segítek tervezni), szóval kurvára a szenvedő fél vagyok. És nyilván hosszabb az átfutás, cserébe imho nem felesleges. Amit lehülyeségezel, az pl hosszú távon sokat segít abban, hogy érthető maradjon a kódbázis (de tény, hogy oda kell figyelni, hogy ne menjen el nitpicking irányába). Általában a review folyamat ilyentén megléte tapasztalataim szerint rohadt sokat segít, mert az emberek megtanulnak reviewzható kódot, meg kommitokat csinálni, hogy ne legyen a review fájdalom (tehát neki ne kelljen sokat várni, stb stb...), ami coincidentally kurva jól fog jönni, mikor majd hozzá kell nyúlni ahhoz a részhez később :)

Illetve ugyanez miatt egyébként az egyik leghatékonyabb mentoring/knowledge sharing eszköz. Ami egy kicsit át is visz a másik gondolatomhoz, hogy ez a "a fejlesztő kizárólag a saját kicsi izéjével akar foglalkozni, és véletlen se kelljen semmi mással, csak amit Ő! vállalt a sprintben"... szóval értem, de ez nem egy one man show. Érték van abban, hogy legalább 2 embert érti nagyjából, hogy mi van ott, hogy összesciszolják kb a coding stylet, szóval egységesebb érzete lesz az egész codebasnek. Elég gyakran látok olyat is, hogy még azért itt esik ki bizony a másik szemlélőből ez-az, hogy te, x-el mi van ilyenkor.

Szóval all in all, vannak ebben jogos gondolatok, de imho a review bizony egy tök jó eszköz, de azzal egyetértek, hogy rendes agilisan arra kell figyelni, hogy valódi problémáink megoldásában segítsen. És kell rajta gondolkozni, hogy adott dolgot nem  jobb-e máshol (tipik, hogy a nagybazmegek, amiket mondtál jellemzően már a planningnél fel kéne merüljenek)- Nekem az a tapasztalatom egyébként, hogy egy nem mature teamnél rohadt hasznos ez, ahogy egyre érettebbek, egyre kevesebb konkrét hasznot hajt, viszont nem is fáj. És ha meg be kell integrálni új embert, akkor megvan a processzben a keret hozzá, nem kell külön hullahopp karikákat átugrani.

Illetve írod, hogy ti lazy review, és összeségében bólogatok, csak nem nagyon látom magamban, hogy ebből pl a story ticket alapú reviewink miben különböznek ettől lényegesen. (Igen, még olyat is szoktunk csinálni, hogy ja, ezt úgyis bántjuk még nemsoká, majd ott nézzük át alaposabban, mert tudomásul vettük, hogy ez itt egy interim megoldás. Bár ezzel is az a tapasztalat, hogy ha jól van bontva, akkor ami elkészül, arra már nagyrészt lehet építeni)

Meg ez a nincs nyomás, mert mondjuk release előtt csináljuk... Háááátizé, vannak kétségeim :D

A csapaton belüli pullreq szerintem hülyeség, arról beszéld le aki felhozza ötletként.

nálunk konkrétan a legjobb dolgok egyike. minden pr-nak vannak linkelt issue-jai, így minden rendezett. ha saját projektet csinálok, akkor is így csinálom

4 és fél éve csak vim-et használok. elsősorban azért, mert még nem jöttem rá, hogy kell kilépni belőle.

A csapaton belüli pullreq szerintem hülyeség, arról beszéld le aki felhozza ötletként

Buildet, unit-tesztet, statikus kódanalízist, security scant ésatöbbi azért elegánsabb, ha a CI a pull/merge request-be köpi vissza és az lehet gating item vagy a peer reviewhoz a beugró.

Ha nincs pullreq akkor ezt hogy ellenőrzöd? Bemondásra?

>Ha nincs pullreq akkor ezt hogy ellenőrzöd? Bemondásra?

A pusholó fejlesztő ellenőrzi best effort (lehet persze szabályozni is, hogy mi a minimum), és utána amikor benn van a masteren, akkor a build szerver ellenőrzi.

Egyébként ha a pull req csak a automata ellenőrzéseket csinál, azzal még nincs is bajom, én a kötelező review ellen vagyok csak.

Nyilván az automata ellenőrzéseknek kellően gyorsaknak kell lenniük, hogy ne akadályozzák a munkát. Ha akadályozzák, akkor jobb ha csak utólag futnak le.

No offense de ez nagyon nem jo, hogy masterre merge _utan_ fut csak a CI es elotte nem. 
 

Nyilván az automata ellenőrzéseknek kellően gyorsaknak kell lenniük, hogy ne akadályozzák a munkát. Ha akadályozzák, akkor jobb ha csak utólag futnak le.

Egyetertek, ezert fontos a failfast alapelv. 

Szerintem az az elvárás, hogy minden kommitnak "jónak kell lenni", nem ad annyit, amennyibe kerül. Egy virtuális achievment kedvéért adjuk fel a produktivitást.

Talán ott lehet megfogni a kérdést, hogy két konfliktusban lévő igény van:

 * Legyen egy fejlesztői ág, ahol először találkoznak a fejlesztések, azaz itt kerül be a közösbe a munka eredménye, a kommit.

 * Legyen egy ág ahonnan release-elünk.

A kettő egybe van gyúrva, és a fejlesztői ág úgy van kezelve, mintha annak minden pillanatban release-re alkalmasnak kellene lennie. Értem én, hogy ez jó dolog volna önmagában, ki ne akarnak minden kommitból releaselni? Csak nem számolnak a rejtett költségeivel, ami a csillagokig ér. Véleményem szerint nincsen rá bizonyíték, hogy így hatékony, vagy ésszerű dolgozni, egyszerűen csak egy cargo-cult áldozata az ipar nagyrésze, és mindenki így csinálja, mert így szokás.

Nem feltétlenül van egybe gyúrva.  Nálunk egy ideig volt dev branch és master branch.  A master-be csak akkor merge-eltünk a dev-ről, ha release készült, a dev branch-nek ekkor kellett csak "teljesen jó" állapotban lennie (bár az igaz, hogy törekedtünk a "közel teljesen jó" állapotra minden dev-be menő merge-nél is).  A fejlesztések külön feature branch-eken mentek amik a dev-et célozták.  Végül arra jutottunk, hogy _nekünk_ nem ad hozzá sokat ez a dev branch és csak lassítja a release-t.  Most csak a master van és feature branch-ek, és a master-t igyekszünk mindig release-elhető álapotban tartani, de tényleges release nem készül minden commit-ból, így belefér, ha a master "kicsit törik" (itt leginkább szemantikai törésről lehet szó, bukó tesztekkel, nem forduló kóddal nem lehet lehet PR-t merge-elni).

 

Szerintem egyébként viszonylag könnyen tartható elvárás, hogy "nagzon törött" kód ne kerüljön a master-re (feature flag-ek, stb), így ha hirtelen kell egy release, akkor azért viszonylag nagy biztonsággal lehet az aktuális master-ből release-elni.  Ha éppen flux van, akkor meg az utolsó release tag-ből indul a hotfix, de ez nyílván picit több macera.

kövezzetek meg, de az ördögtől való, ha a kicsit eltört main-t ilyenkor fixáljuk és tag-ra megy ki a release? ami jó esetben a verzio (1.0.3#commithash) 

mert Ádám Évátol az eredeti feat/fix branchen fixálni lehet azért sem lehet, mert két merge impactja lehet maga a bug a main-ban az ok.

A csapaton belüli pullreq szerintem hülyeség, arról beszéld le aki felhozza ötletként.

 

Ezzel nagyon nem értek egyet, szerintem nagyon sok haszna van a PR-nek, review-nak:

- mindenki vet legalább egy gyors pillantást az éppen készülő kódra, így kb képben van a tőle független fejlesztésekkel is.  Holnap lehet, hogy ő dolgozik tovább az adott témán

- a tapasztalatlanabb fejlesztők PR-jain feltehetően lesz javítani való, amit a comment-ek alapján meg tud tenni, így gyorsabban fejlődik

- az új csapattagoknak is sokat segít a PR review a "közös nyelv" megismerésében / kialakításában

- a tapasztalt fejlesztő is hibázhat, vagy indulhat el "rossz irányba".  Számtalanszor előfordult, hogy a javasolt megoldás "jó", de egy másik fejlesztő meglát egy sokkal egyszerűbb / szebb megvalósítást a review során.

- normális eszközzel a javaslatok megvitatása is sokkal egyszerűbb, mint utólag (review nélküli merge után), ráadásul "nyoma marad", később könnyű elővenni a PR-t és megnézni, hogy egy adott döntés miért született

Javaslom, hogy 2 user-rel és egy ingyenes Github fiókkal vagy lokális Gitlab szerverrel próbáljad ki azokat, amiket kérdezel. Látni fogod és megtapasztalni. Talán ez jobban fog segíteni megérteni, ha látod, és nem csak olvasod.

Sakk-matt,
KaTT :)

Visszatértem! A hozzászólásom alatt lévő szavazat gomb nem nyomódik meg magától!

Ahogy csardij is javasolta, valószínűleg érdemes lenne egy-két doksival vagy videóval kezdeni, lehetőleg olyannal, amiben vizuálisan is szemléltetve vannak egyes dolgok.

De röviden néhány érdemi válasz. A git szempontjából repók vannak, amik technikailag egyenrangúak, és elviekben mindig mindenkinél megvan minden history. (Ez nem teljesen igaz, mert lehet vele trükközni, de alapvetően az elképzelés)

Az, hogy a legtöbb projekt esetében vannak speciálisan kezelt repository-k, csak szervezési kérdés. Amit te "megosztott" repónak hívsz, technikailag az is egy ugyanolyan git repó, mint ami a fejlesztő saját gépén van, az csak egy projektszervezési kérdés, hogy a csapat azt tekinti "a közös munka eredményének. (És emiatt erre vannak ráállítva a CI, deployment stb. automatizmusok.) Ő tehát ilyen "egyenlők között egyenlőbb". :)

Ezek között az "egyenlő" repók között lehet "tologatni" a commitokat tetszés szerint (nyilván jogosultságok alapján, nem ész nélkül). Git esetén amúgy működik az is, hogy te megcsinálsz valamit a helyi gépeden, majd szólsz "a Jóskának", hogy nálad van egy ilyen meg ilyen branch, amire ránézhetne. Na, ő ilyenkor le tudja húzni tőled azt a branchet, tehát nem muszáj neked push-olni. (Nyilván ehhez megfelelő setup kell a te gépeden is, hogy elérje, de nem nagy truváj.)

A fentiekből is következik, hogy ha te a saját fejlesztői példányodat befrissíted egy távoli repó (remote) alapján, akkor nálad is minden meglesz, ami a távoli repóban megvan (szintén lehet vele trükközni, de ez az alapelv). Így tetszőlegesen tudsz a saját gépeden nézelődni, összehasonlítgatni más munkájában/-val is.

Viszont, hogy te épp a repository melyik branchében dolgozol, és melyik commitból kiindulva, az már a te döntésed.

Fontos, hogy amikor egy helyi könyvtárba leklónozol egy távoli repository-t, akkor alapértelmezés szerint neked abba a könyvtárba két dolog is fog kerülni.

  1. A "working tree", azaz a tényleges fájlok, amin tudsz dolgozni, és
  2. egy .git alkönyvtárban a teljes repository, ami a te saját használatú példányod. Innen tudsz checkoutolni, ide tudsz commitolni, innen tudsz távoli repóba mozgatni commitokat, és ide frissül az is, amit a távoli repóból húzol le. (Szét lehet szedni, hogy ne ugyanabban a könyvtárban legyen a working tree és a git repó, de ez a legtöbb esetben nem szükséges.)

Amire neked szükséged lesz kezdetben:

(1) Helyi (.git alkönyvtár) és távoli repó közötti műveletek:

  1. clone: távoli repó alapján üres helyi könyvtárba létrehoz repót, working tree-t
  2. fetch: távoli repóban lévő módosításokat beszinkronizálja a helyi repódba (.git könyvtár)
  3. push: helyi repóban lévő módosításokat átküldi a távoli repóba

(2) Helyi (.git alkönyvtár) repó kezelése:

  1. log: ezzel tudsz nézelődni a teljes history-ban (minden, ami megvan neked már helyileg)
  2. merge: ezzel tudod egy másik branch módosításait behúzni a saját branchedbe (hogy X branchen ki dolgozott, teljesen mindegy, a lényeg, hogy nálad meglegyen pl. fetch után). Tapasztalatom alapján a git elég ügyesen össze tudja merge-elni akár az ugyanazon fájlban lévő módosításokat, de azért nem mindenható, vannak conflictok. (Ezek feloldásához én javaslom valamilyen vizuális git eszköz használatát.)
  3. rebase: egyik branch commitjait egy másik után tudod vele fűzni. Kezdőként kicsit bonyi lehet, de érdemes tudni róla, hogy van ilyen. (Projektmenedzsment szokta eldönteni, hogy szabad-e/kell-e és milyen körülmények között használni, hitviták tárgya. :) )
  4. diff: lényegében a helyi repó két különböző állapotát (pl. két branch között mik változtak) tudod vele összehasonlítani
  5. branch: ezzel tudsz helyi branchet készíteni, branchekről infót lekérni stb.

Sok helyen találkozhatsz a pull paranccsal is, én személy szerint egyáltalán nem használom. Ez gyakorlatilag egy fetch + merge vagy egy fetch + rebase (konfigurációtól és aktuális állapottól függően).

(3) Helyi repó és working tree közötti dolgok:

  1. checkout: working tree fájljait frissíted a helyi repó egy adott commitjának megfelelő állapot alapján
  2. commit: ezzel hozol létre új commitot, amit a helyi repóban (.git) fog tárolni (onnan ugye push-sal tudod továbbküldeni)

Itt ezt egy kicsit leegyszerűsítettem, mert a helyi repó és a working tree "között" vagy egy ún. index is, amibe tudod gyűjtögetni (stage) a módosításokat, mielőtt commitolnál. Tehát pontosítva a commit nem közvetlenül a working tree-ben végzett módosításaidat tolja be a helyi repóba, hanem amit commit előtt betettél az indexbe. Ehhez kell az add parancs.

(4) Working tree-re (és indexre) vonatkozó dolgok:

  1. status: ezzel tudod lekérdezni, hogy a working treeben lévő fájljaid milyen állapotban vannak ahhoz a commithoz képest, ami alapján elkezdtél dolgozni (legutolsó checkout óta)
  2. add: working tree adott módosításait teszi be az indexbe (ahonnan majd megy a commit a helyi repóba)

Nagyjából ez a logikája az egésznek, meg persze egy halom egyéb parancs, opció stb. van, direkt nem mentem bele. Érdemes az egyes parancsok súgóit is olvasni, mert van bennük egy csomó hasznos infó.

A branchekről érdemes még annyit tudni kezdetben, hogy a git nyilván tud tartani megfeleltetéseket a saját lokális brancheid és a távoli branchek között (tracking-nek hívják itt). Ennek a lényege, hogy a távoli brancheken nem közvetlenül dolgozol, hanem "helyi példányokon". Gyakorlatban ez úgy néz ki, hogy ha pl. a "közös" repóban van egy cool-feature nevű branch, akkor az nálad egy clone vagy egy fetch után úgy fog látszódni, hogy remotes/origin/cool-feature. Ha ezt akarod checkoutolni a working tree-dbe, akkor ez úgy fog történni, hogy létrejön egy köztes helyi branch cool-feature néven, és az lesz checkoutolva, azt tudod módosítgatni szükség esetén (tehát közvetlenül a remote brancheket nem piszkálod). (Ezt úgy tudod megtenni amúgy pl., hogy git checkout -t remotes/origin/cool-feature)

Ezt csak azért írtam le, mert fogsz találkozni olyannal, hogy egy adott branch helyi változata és a távoli változat (tehát a cool-feature és a remotes/origin/cool-feature) "el lesz csúszva" egymáshoz képest, attól függően, hogy melyik változott. Ilyenkor a helyit egy merge vagy egy rebase segítségével fel lehet zárkóztatni a távolihoz (vagy ha nem volt helyi módosítás, akkor törlöd a helyi branchet, és újra checkoutolod a távolit), illetve a távolit egy push segítségével fel lehet zárkóztatni a helyihez.

Még valami: git-nél várhatóan fogsz találkozni a pull/merge request fogalmával. Ez technikailag nem a git része, hanem egy out-of-channel mechanizmus arra, hogy X fejlesztő tudja jelezni: "nekem van egy ilyen branchem, ebben ezt meg ezt csináltam, legyetek szívesek ennek a módosításait beintegrálni egy másik repóba" (jellemzően az általad "megosztottnak" nevezett repó a cél ilyenkor). Aztán ezt a requestet meg lehet köpködni minden oldalról, és amikor mindenki elégedett (LOL), akkor vagy Y fejlesztő rányom, hogy "merge", és akkor a célrepóba is bekerül, amit X fejlesztő gyártott, vagy elutasítják, és akkor vagy dolgozik még rajta vagy kuka.

Itt a lényeg, hogy a PR/MR a git szintje felett van, inkább menedzsment jellegű eszköz, mint technikai (persze ennek is van egy csomó technikai vetülete).

Röviden ennyi. :) A "hogy épülnek egymásra a commitok", "mik azok a branchek gitben", "hogyan lehet rámutatni egy branchre/commitra/egyébre" témákat meghagyom a netes doksiknak. ;)

Köszönöm a részletes hozzászólást!

"A git szempontjából repók vannak, amik technikailag egyenrangúak" Ezzel egy picikét vitatkoznék. A helyi repót "git init" utasítással hozom létre, míg a távolit "git init --bare" utasítással. Már eleve másként jön létre, nem lehet egyenrangú. A helyi repó által tárol állományokat le tudom kérdezni "git ls-files" utasítással, addig az utóbbit nem tudom megtenni.

Gábor

Jogos, bár én a "bare" repókat nem kezdő feature-nek tekintem. :) Amúgy maguk a repók ilyenkor is egyenrangúak, csak a bare repóhoz nem lesz working tree. De a bare repó technikailag ugyanaz, mint ami egy "sima" helyi repó esetén a .git könyvtárban van. Ha két helyi repóval játszol, akkor sem muszáj a távolinak bare-nek lennie, legfeljebb picit másképp paraméterezed a parancsokat. 

Ha függetlenül hozod létre őket, akkor egy picit macerásabb, mert alapvetően nem lesz bennük közös, de összefésülhető.

Pl. ha van egy $HOME/gittest/A könyvtár, amiben van egy git init-tel létrehozott "sima" repo, akkor azt simán le tudod klónozni úgy, hogy

git clone $HOME/gittest/A $HOME/gittest/B

tehát a remote-od "URL"-je lehet egy sima helyi könyvtár elérési útja is. Innentől kezdve B-ben úgy látod A-t, mint egy távoli repó, tudsz fetch-elni, pusholni, stb.

Ha nem klónozol, hanem init-tel csinálod mindkettőt, akkor meg git remote paranccsal tudod távoli repóként hozzáadni egyikhez a másikat.

Kieg.: ha jól emlékszem, bare repó esetén is ugyanez a logika.

Szerkesztve: 2025. 01. 07., k – 10:29

> 1. Jól értelmezem, megosztott repóban levő állományok listáját csak úgy tudom lekérdezni, hogy azokat lehúzom a lokális repóba? A lokális repó listázható az ls-files paranccsal, de ugyanezt hiányolom a megosztottra.

Vannak jó kis grafikus kliensek, pl. a SourceTree, illetve a szerver is adhat webes felültetet (github, pl.)

> 2. Ha olyan állományt módosítok, ami közben megváltozott, mert más fejlesztő is hozzányúlt, milyen hatékonyságú az összefűzése? Ha ugyanolyan minőségben tudja összefűzni, mint az általam eddig látott összehasonlító programok mutatják az eltéréseket, akkor agyhalál lesz megtalálni, mit kutyult össze a kódban...

Csodák nincsenek, a share-update egy izgalmas műfaj. Az is egy opció, hogy csak pull-request-eken keresztül lehessen módosítani, nagyon meggyorsítja a fejlesztést.

Mindenesetre a legjobb dolog az egészben, hogy nem kell verziószámokat követned, elég ilyesfajta hash-eket megadni:

git diff be1be1b821a4920fd8f0ae143a6f53ab56f0ea63..7a1e0e42ca49cbc62782816e7bd583c9ae93a4e5

Kiegészítő olvasmány:
https://stevebennett.me/2012/02/24/10-things-i-hate-about-git/
https://explainxkcd.com/wiki/index.php/1597:_Git

Ha van rá mód akkor próbál úgy kiosztani a feladatokat és úgy szervezni a kódot hogy minél kevesebb merge legyen. Például ha 3000 soros osztályon dolgoztok többen, akkor azt érdemes lenne szétszedni, meg amúgy sem egészséges. :)

Szerkesztve: 2025. 01. 07., k – 13:21

A git-et elegge idoigenyes megtanulni, de szinte mindent meg lehet benne csinalni. Visznt ugy latom, hogy itt alap filozofiai kerdeseket kell tisztazni. Ahogy elottenm is irtak erdemes megerteni az alapokat, mi az a staging, working tree, a remote, a HEAD, a branchek es remote branchek, a merge vs. rebase kozti kulonbseg(ek), stb. stb.

Itt van mingyart az a kerdesed hogy meg akarod nezni mi a kulonbseg a remote es a sajatod kozott. Minek? Ha ugy kezdted a munkat hogy pull-oltal, akkor a changek azok amik a staging-en vannak vagy ha mar kommitoltad oket vagy mondjuk stash-oltad oket, de mindenesetre az a kulonbseg amit Te helyileg csinaltal. Maximum akkor lehetne ez erdekes ha tenyleg egy tobbtizezer soros allomanyon dolgozik 5-10 ember egyszerre. De az igen nagy gaz lenne, ott valami el lenne kefelve mukodesi szinten.

De elkezded az alapoktol, aztan egy-ket honaon belul mar batran csinalsz rebase-t a masteren barki tudta nelkul :D

Rengeteg jo oldal van ami vegigvisz ezeken. En is had ajanljak valamit: https://www.atlassian.com/git

Szia!

Köszi a linket, ezt is meg fogom nézni.

Igen, nehéz átlátni, mert eddig VSS-el dolgoztam, illetve Delphi alatt Jedi VCS-el, mindkettőnek alapvetően más a technikája (mindkettő kölcsönzős módszert alkalmaz, egyszerre csak egyvalaki szerkeszthet egy állományt).

A kérdéseim okát nem mindig fejtem ki teljes mértékben, mert akkor kisregény a vége, a kérdés lényege pedig elveszik :)
Eddig is automatizáltam a fejlesztés élesítési folyamatát, ennek két lépése van nálunk:
1. A módosításaim kiírása a fejlesztői verziókezelő rendszerbe, ehhez van egy saját fejlesztésű programom, ami a VSS-ből lekérdezi, mely állományok vannak nálam kikölcsönözve, ezeket feldobja nekem egy ablakban, ahol egyesével tudok megjegyzéseket írni hozzájuk, majd a végén az általam engedélyezett állományokat visszaírja (check-in) a VSS-be, valamint ki is másolja azt egy megosztott mappába.  Ez a lépés bárhányszor ismételhető, amíg úgy nem döntök, élesíthető az elkészült kód.
2. A tényleges élesítésre is van egy saját programom, ez az előző program által mappába kirakott állományokat kikölcsönzi (check-out) az éles verziókezelő rendszerből (szintén VSS), bemásolja az állományokat az éles szoftver könyvtárába, lefordítja azt, majd az elkészült állományokat (exe, dll, stb) átmásolja a megfelelő helyre, végül visszaírja (check-on) azokat a VSS-be.

Természetesen ezekben megfelelő hibakezelés van, így ha valami nem kerek (pl nem fordul le az éles program), akkor az adatvesztés nélkül orvosolható.

És igen, jól írtam, két, egymástól független verziókezelő rendszer van: fejlesztői és éles. Ennek nagyon praktikus okai vannak:

- A két VSS két külön vason van, így ha az egyik meghalna, van mihez nyúlni (természetesen mindkettőről megvannak a megfelelő mentések is)

- Ha az éles rendszerben hibát találnak, ami érint épp fejlesztés alatt levő rutint, megoldható a hiba javítása a nélkül is, hogy meg kelljen várni a folyamatban levő fejlesztés végét. Nem egyszer volt már erre szükségem. Igen, tudom, ezt ebben az esetben mindkét helyen javítani kell. A Gitben ugyan erre vannak a branch-ek, de nem vagyok abban biztos, hogy ennyire el szeretném bonyolítani a dolgokat...

 

"meg akarod nezni mi a kulonbseg a remote es a sajatod kozott." Ez nekem lett volna segítség, hogy ha meg tudtam volna tudni az általam már commitolt, de még push-olt állományok különbségét, akkor egyszerűsíthetném a munkámat bizonyos szituációkban.

 

Nem dobozos szoftvert fejlesztek. Egy teljesen más területen működő cégcsoportnál vagyok fejlesztő, a cégcsoport saját ügyviteli rendszerét fejlesztem többségében egyedül. Eddig VS2019-et használtam, de nem ártana váltani újabbra (VS2019-re), de a VSS csak 32bites, a VS-ből pedig a 2019 az utolsó 32bites környezet. Váltás esetén a már megírt segédprogramjaimat csinálnám meg úgy, hogy a git-et kezelje, miközben ugyanazt a funkciót nyújtja számomra, mint a VSS alatt. Ezért szólnak ezek a kérdéseim.

Gábor

>> Ez nekem lett volna segítség, hogy ha meg tudtam volna tudni az általam már commitolt, de még push-olt állományok különbségét, akkor egyszerűsíthetném a munkámat bizonyos szituációkban.

git fetch someremote
git diff somebranch someremote/somebranch

Szerintem a két VSS két branch lehet a git-ben, és biztonsági mentés pedig egy külön kérdés, a központi git-et rendszeresen menteni kell és kész.

>A Gitben ugyan erre vannak a branch-ek, de nem vagyok abban biztos, hogy ennyire el szeretném bonyolítani a dolgokat...

Ez szerintem egyszerűbb mint két verziókezelőt tartani.

> Különbség nézés

Bármely két commit között (különböző ágak, vagy egymás utáni kommitok) között tudsz különbséget nézni a git difftool -d paranccsal. Ha be van konfolva, akkor egy GUI-s könyvtár összehasonlító programot indít. Én a meld-et használom (lásd: https://meldmerge.org/ ), az a kedvencem, de van több ilyen eszköz is.

Hasonlóan a merge-hez is be lehet állítani külső toolt, ami 3 way merge-öt kezel: látod a közös őst és a két állapotot a két ágon. Erre is meld-ez használok.

 

> ami a VSS-ből lekérdezi, mely állományok vannak nálam kikölcsönözve, ezeket feldobja nekem egy ablakban, ahol egyesével tudok megjegyzéseket írni hozzájuk, majd a végén az általam engedélyezett állományokat visszaírja (check-in) a VSS-be,

Ez nekem olybá tűnik, hogy a commitot szétszeded utólag fájlokra, hogy külön commentet kapjanak. Bár én ilyet nem csinálnék, de erre is van lehetőség, a commitokat tudod utólag szerkeszteni git-tel (de nem biztos, hogy egyszerű elsőre).

> Ez a lépés bárhányszor ismételhető, amíg úgy nem döntök, élesíthető az elkészült kód.

Egy feature branchen reszelgetheted a kommitjaidat ameddig csak tetszik, ez is megoldható git-tel.

>A tényleges élesítésre is van egy saját programom

Ez a lépés csak egy merge: az előkészített feature branch-et merge-ölöd az integrationbe (master, main, stb, sok neve lehet). Ezzel felülírod ott a fájlokat, ez a merge lényege. Utána a főágra tett trigger indít egy buildet, és az autobuild elkészíti az exe-ket, meg bemásolja ahová kell - ez már ugye build automatizálás kérdése.

Igen, azt értem, hogy a Git-ben erre vannak a branch-ek. Egy dolog, ami nincs: egy gépen lenne a dev és az éles ág is, hisz egy Git repo tárolná őket. A két VSS (ami igazából csak két megosztott könyvtár két különböző szerveren, a VSS ugyanis csak kliensen van telepítve, nincs szerveroldala) viszont két különböző gép, nem véletlenül.

"Ez nekem olybá tűnik, hogy a commitot szétszeded utólag fájlokra, hogy külön commentet kapjanak"

Minden egyes módosult állományra van lehetőségem külön megjegyzést írni. Jól jöhet, ha utólag kell megnéznem, miért változott az adott állomány egy commit során. Látom, hogy a Git-ben ez alapvetően nem így van, de ezen ráérek még sakkozni. A VSS a Git-el ellentétben nem snapshot-ot csinál, hanem fájlonként tárolja el a verziókat.

Programozásban tipikus, hogy egy logikailag összetartozó változás, ami együtt érvényes, az több fájlt módosít egyszerre. Például egyik fájlben módosítasz egy metódust - mondjuk hozzáadsz egy új paramétert - és minden felhasználási helyén is hozzáadod. Ez a módosítás egyben értelmes, ezért az összes fájlon végzett módosítás együtt egy commit.

Ha vissza akarod követni, hogy miért lett az adot sor odaírva, akkor a git blame megmutatja soronként, hogy mi melyik committal került be. A webes megjelenítők linket csinálnak a sorból, ami a commitra mutat, és azonnal látod a commentet és az összes vele egy kommitban történt változást is.

Lehet, hogy tényleg érdemes lenne hátralépned egyet, és elgondolkozni azon, hogy a valós problémáid gittel hogy jó megoldani, nem pedig azon, hogy az eddigi megoldást hogyan lehet kifacsarni a gitből. Mert ez pl olyan, ahogy már írták is, hogy ez tulajdonképpen kiderül könnyen csak -- és ez még így explicit talán nem hangzott el, pedig imho az egész git felfogásának, és a frusztráció elmúlásának kulcsa -- meg kell érteni, hogy a git, sok mással ellentétben nem fájlok állapotával dolgozik alapvetően, hanem change setekkel, és azoknak a gráfjával. Egy commit az egy change set, ebben és ebben a fájlban ez és ez változott. És akkor rögtön kiderül, hogy valójában a miért változott az maga a commit leírás. Egy commitba egy összetartozó változás megy. Ha több dolog miatt kell basztatni egy filet, akkor több commitban lesz benne. De nem az egész fájl, csak az a konkrét diff.

És akkor az is kiderül pl, hogy nem kell félni attól, hogy túlbonyolítod a brancheléssel, mert nem akartad. A gitben a branch olcsó, egyszerű, gyakorlatilag azt mondod, hogy innen kérek egy új faágat. Másolni nem kell semmit sehova. És mivel a commitok csak changesetek, ezeket nem nehéz mozgatni, mert ez egész ágat át lehet tolni akárhova, nem baj, hogy ugyanazon a fileon dolgozik több, nem lesz ebből iszonyat szívás, csak azzal kell külön foglalkozni, amikor konkrétan ugyanazt a részt pisztergálja valaki.

Struktúrált kód (pl XML) esetén a merge felejtős. Még conflict sem kell ahhoz, hogy elrontsa!

4. Push-al felteszem a közösbe.
[...]
mi történik, ha a 4. lépés előtt történik a közös repóban egy változás?

Lehet, hogy az, ami egy korábbi munkahelyemen is történt ilyenkor a saját wikinkkel: tele lesz a história ilyen ~`Merge branch jgipsz/master into master` "elköteleződési üzenetekkel" (:P). Ez majdnem olyan gyönyörű, mint egy olyan bejegyzés, hogy "revert: revert: revert: revert: revert: revert: revert: <akármi>". (És ha valaki jgipszszel egy időben kezdett valamin dolgozni, de ő jgipsz után küldené be a "közös" távoli masterbe, akkor lehet, hogy nem lesz őszinte a mosolya.) De ezért is illik többemberes repó esetén mindig saját ágon dolgozni, aztán ha eljön az ideje, mehet a pull request / merge request (az esetleges ütközéseket meg mindenki oldja meg maga).

Szerkesztve: 2025. 01. 07., k – 21:25

A git sokmindenre jó, de csak egy ember fejlesztését tudja rendesen nyomon követni, közös kódbázis kezelésére tökéletesen alkalmatlan.
A megoldás: valamilyen webes frontend használata, ami pótolja a git hiányosságait (gitee, github, gitlab stb.), különös hangsúllyal a PR-ek kezelésére. Ha többen is dolgoznának egy git repón, felejts el minden mást, csakis PR, kevesebb ősz hajszálad lesz.

Mivel időközben másik fejlesztő módosíthatott az állományokon, ezért kell egy lépés a 3. pont után, amiben ismételten lehúzom a közös repóból a változásokat, ez elvégzi a változások összefűzését.
Az itt felmerült kérdésem: mi történik, ha a 4. lépés előtt történik a közös repóban egy változás?

Összefossa magát a git és nem fog engedni push-olni, még akkor sem, ha triviális lenne a két változat összefésülése (azaz ha nincs átfedés a módosítások között, pl. másik függvény változott, mint amit te módosítottál). Erre a git képtelen.

Elvileg itt lenne ez a merge, de én már annyiszor megszoptam vele, hogy inkább teljesen kizártam a workflow-mból. Ha másvalaki időközben belemódosított, és emiatt besír a push, akkor inkább pull (és fetch-rebase) helyett leklónozom a módosított remote repót egy másik könyvtárba, lokális diff, és átkopiszatázom bele a módosításaimat kézzel, egyesével, majd az új könyvtárból commit+push, a korábbi lokális git repó meg töröl.

Nem szép, iszonyat gány megoldás, de higgy nekem, SOKKAL időkímélőbb és időhatékonyabb, mint bármi más gites ökörködés (bónuszként a git history-t sem b*assza össze). Megjegyzem, a PR is lényegében pontosan ugyanezt csinálja, csak épp az remote oldalon duplikálja le és diffeli a repót.

(Itt általában az szokott felmerülni, hogy kézzel, egyesével átkopipasztázni a módosításokat macerás, de ha rendes gyakorisággal van commitolva, akkor minimális lesz, és végeredményben gyorsabban elkészülsz vele, mint ha rebase conflicttal bohóckodnál.)

A git eddig nekem tökéletesen teszi a dolgát (a pull is), semmi ilyet nem tapasztaltam, pedig jó régóta használom közös kódbázisokon, és már minden is volt.

El tudok képzelni olyan szituációt, ahol egyszerűbb valamit kézzel visszamásolni, pl több branch, amik egymásból ágaznak, az egyik össze-squasholva vissza lett merge-ölve a main-be, a másikat pedig rebase-elni akarod a main-re, de közben minden is át lett írva. De ez is megoldható. -> de ez a ritkább eset, és nem kell ekkorákat "kavarni" :) De ez:

Ha másvalaki időközben belemódosított...

egy alap eset, amit tökéletesen kezel.

---

@Luckye Egy kezdő git tutorial elolvasását, vagy youtube videó megnézést javaslom neked (15 perc-től 1-2 órások lehetnek), az alap dolgokat nézd meg. Annál jobban itt senki nem tudja elmondani, ezekben jól össze van szedve. És kezd el közben használni, és akkor kérdés esetén (pl mi legyen, ha valaki más közben push-olt) akkor rögtön látni fogod, hogy hogyan működik. Egyébként beállítható, hogy a pull esetén merge legyen, vagy pedig rebase-elje a Te commitjaidat a branch tetejére. Javaslom, hogy nézd meg azt is, hogy mi a különbség a kettő között a history-ban utána.

El tudok képzelni olyan szituációt, ahol egyszerűbb valamit kézzel visszamásolni, pl több branch, amik egymásból ágaznak, az egyik össze-squasholva vissza lett merge-ölve a main-be, a másikat pedig rebase-elni akarod a main-re, de közben minden is át lett írva.

NEM. Alapesetről beszélünk.

egy alap eset, amit tökéletesen kezel.

Meg egy nagy lótúrót, dehogy kezeli.

Reprodukálás:
1. csinálj egy github repót, egyetlen main branch-el
2. klónozd le lokálba
3. módosíts, commit-olj
4. az egyszerűség kedvéért a webes editorral módosítsd a README-t
5. és most próbálj meg push-olni

Hiába állítod az ellenkezőjét, nem fog menni, a git NEM képes kezelni ezt a legegyszerűbb esetet sem, pedig nincs több branch, nincs egymásból ágazás, nincs history squash, nincs se semmi, faék egyszerű minden.
Helyette egy ilyen hibaüzenetet fog kiokádni:

! [rejected]         main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/valami.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Vagy ezt: https://media.geeksforgeeks.org/wp-content/uploads/20240711092459/ad222…

A legszebb az egészben, hogy a hibaüzenetben javasolt "git pull" is csak akkor működik, ha különböző fájlok módosultak, egyébként rebase / merge kell(ene). Sok-sok éves tapasztalatból mondom, hogy ilyenkor hatékonyabb újra leklónozni, átrakni a módosításokat, onnan commit+push, régi töröl. Rengeteg időt spórolsz meg, sokkal gyorsabban megy, mint bármiféle git paranccsal szarakodni.

Próbáld csak ki! Pár egyszerű lépésben ellenőrizheted, hogy tényleg így működik-e a git!

nagyobb hibázási lehetőséggel

Már megint hazudsz, egy git diff egyszerűen megmondja, mindent átraktál-e. Közben meg merge-nél nincs is lehetőséged menetközbeni diff-et futtatni, és a rebase sem működik, ha conflict van.

szofver (amit erre találtak ki)

Hogy mire? Te az előbb még azt is tagadni próbáltad, hogy egyáltalán létezne a probléma. Most meg már létezik a nem létező problémára célszoftver? (És csak a miheztartás végett, sosem állítottam, hogy ne létezne a git-ben rebase vagy merge, csak azt, hogy egyszerűbb és gyorsabb annélkül csinálni.)

Ez van a hazug TROLLokkal, hazug embert könnyebb utolérni, mint a sánta kutyát, most is lebuktál.

Igen, bzt, Te biztos jobban összemerge-ölsz mindent kézzel, mint a git, amit erre találtak ki. :))

Hagyjuk már ezt a hazugozást, nem ugyanúgy látjuk a dolgokat. Tizensok éve használom a git-et, nem fogod ezt most megmagyarázni, hogy a git sz*r. Köszi.

Szerk: a teljesség kedvéért a példád, mielőtt azt mondod, hogy nem próbáltam ki (de már sokszor kipróbáltam):

Default beállítások:

git config --global init.defaultBranch main
git config --global pull.rebase true

Hozz létre három repository-t:

mkdir a b c
cd a
git init
cd ..

cd b
git init
cd ..

cd c
git init --bare
cd ..

Add hozzá a az "a"-hoz, "b"-hez a "c"-t mint remote repo-t:

cd a
git remote add origin ../c
cd ..

cd b
git remote add origin ../c
cd ..

Commitoljunk az "a"-ba, és pusholjuk "fel":

cd a
echo "Ez egy readme fájl." > readme.txt
git add readme.txt
git commit -m "Add readme.txt"
git push --set-upstream origin main
cd ..

Leszedjük a b-ben:

cd b
git pull origin main
cd ..

Commitoljunk megint az "a"-ba, és pusholjuk:

cd a
echo "Ez egy readme fájl. #2" >> readme.txt
git add .
git commit -m "readme.txt 2"
git push
cd ..

Majd a "b"-be is:

cd b
echo "teszt" >> readme.txt
git add .
git commit -m "teszt b"
git push --set-upstream origin main

Itt jön a hibaüzenet, amin megakadtunk (ami teljesen jogos, és normális hogy jön):

git ! [rejected]        main -> main (fetch first)
error: failed to push some refs to '../c'
hint: Updates were rejected because the remote contains work that you do not

És itt pedig a feloldása::

git pull origin main

Ezt kapod rá válaszul:

From ../c
 * branch            main       -> FETCH_HEAD
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
error: could not apply c0151ab... teszt b
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".

Ezen a ponton kell merge-ölnöd, és vedd észre, hogy kiírta a további teendőket:

vi readme.txt
git add readme.txt
git rebase --continue

és voilá, tudsz push-olni:

git push --set-upstream origin main

 

Jogos, hogy merge-ölni kellett?

Igen, mindenképp. Honnan tudta volna kitalálni a git, hogy Te azzal a három sorral mit akarsz, melyik a valid?

Ezt fájl kopizgatással, meg diff-fel nehezebb lett volna összehozni? Ezt a kis példát talán nem, de egy nagy projektben mindenképpen.

Es akkor arrol meg nem is volt szo, hogy a 'vi readme.txt' helyett lehet git mergetool-t is hivni, ami meghivja az altalad bekonfolt, legszivesebben hasznalt mergetool-odat. kdiff3, gvimdiff, whatever.
Nekem negy-ablakra osztott (asszem 3-way diff?) gvim jon be: kozepen a kozos BASE (1 soros readme.txt), balra LOCAL (en changeim, tehat a 'teszt' a masodik sor), jobbra REMOTE (itt a 'Ez egy readme fájl. #2' lesz a masodik sor), alul pedig a MERGED file, amiben el kell _dontened_, hogy mi a helyes, egyik sor, masik sor, egyikse, mindegyik (es milyen sorrendben!).

Teljesen egyetertek, nagyobb pelda eseten a diffek kezi ide-oda pofozasa nagysagrendekkel nehezebb, mint git-tel es mergetool-lal. Persze neha kellhet az, hogy ranezz a master agra egy masik ablakban, akar arra a commitra, amivel konfliktolsz, ha nagyon-nagy a conflict (vesd ossze: line ending change, whitespace (behuzas) formazas, stb.).

Édes istenem a fejlesztők gyöngye, konkrétan annyi a teendő, hogy a saját szarodat rebaseled az origin tetejére. Amit egyébként a git pull meg tud csinálni, ha esetleg a hosszú évek alatt elolvastad volna a man legeslegelső bekezdését, akkor láthattad volna. :) (Ha nem akarod mindig kiírni, hogy --rebase, akkor van rá konfig is). Ez egyszerű esetben kb egy darab parancs, bonyolult esetben meg úgyis kell foglalkoznod a conflict feloldással. (Meg nem a fileokon múlik, hanem hogy volt-e konkrét conflict). És a conflictok kezelésében is tud mindenféle segítséget adni a git, pl értelmesen rendezgetheted, átveheted a commitokat, hogy csak a habot kelljen a végén javítani, és meglegyen, hogy mi történik :D

De nem, klónozzuk újra, és csináljuk meg újra a kommitokat, jézusom.

Szerintem inkább ne ossz tanácsokat git ügyben :)

Asch. :))

BZT: a git nem akarja rápusholni.  Vagy lesz forrássorbeli ütközés, vagy nem.  Ha nem, akkor csöndben összefűzhetné, de attól még lehet szemantikai konfliktus, ami nem derülne ki (még az új távoli módosítás ténye sem).  Tehát vedd észre, hogy új kommit került a távolira, nyomj még egy pullt (tudom, fárasztó gombokat nyomkodni), és nézz rá.

Én tudom, hogy git pull-t kell használni, hiszen így működik a git! Nem azért mert gond van vele, vagy nehézkes, hanem mert így lett kitalálva.

Tisztában vagyok vele, hogy push előtt le kell szedned a feltett dolgokat. :) Nincs mit kipróbálni rajta.

És igen, merge-ölni, rebase-elni kell a fájlokat, de ettől még tökéletesen műdödik. Szándékosan működik így.

Sok-sok éves tapasztalatból mondom, hogy ilyenkor hatékonyabb újra leklónozni, átrakni a módosításokat,

Hidd el, hogy van olyan repository, amin többen, és sokat dolgoznak, amit Te nem fogsz kézzel kezelni, hogy másolgatod a fájlokat, mert nem fogod tudni követni. Erre jó a git. Én is sok év tapasztalatából mondom.

Csak annak aki most kezdi el megtanulni ne mondd  azt, hogy nem jól működik, és inkább kézzel kell másolgatni, mert ez nem igaz alap esetben, csak nagyon nyakatekert esetekben maximum.

Tudom, ismerem a működését, csak én ezen nem akadok fent, mert tudom, hogy hogyan kell használni. Mit kell reprodukálni? Az normális működés, amit írsz, szándékosan van így! Bocs, nem bántó akarok lenni, de légyszi először a saját házad táján keresgélj, hogy mi hiányozhat.

@Luckye Még egy tanács, esetleg jó ötlet lehet: Ne valami grafikus vacakkal kezd el használni (ha ez felmerült), hanem rendesen a parancs sorból. Utána ha segít, akkor használj valami gui-t. + És a webes felületek használata mellett is (gitlab, stb.. ami össze tud neked műveleteket vonni, és neked csak egy gombnyomás)  először mindenképpen a parancssoros git-et értsd meg, ahol lépésről lépésre kell használnod. - Szerintem így hatékonyabb lesz, mint ha valami elfed előled valamilyen működést.

A git sokmindenre jó, de csak egy ember fejlesztését tudja rendesen nyomon követni, közös kódbázis kezelésére tökéletesen alkalmatlan.

Eközben a Linux kernelt gitben kezelik, mivel konkrétan ehhez írta Linus. A Windows kódbázist is egy nagy git repoban kezelik (monorepo). Konkrétan annyira jó lett a git, hogy a többi verzió kezelő kihalt. Ma már nem kérdés mit használunk verzió kezelésre.

Szerkesztve: 2025. 01. 07., k – 23:18

Néhány - nekem legalábbis :) - szemléletformáló dolog:

Egy git repoban van egy halom bogyó (minden commit csinál egy újat) amiknek egyedi neve van (commit hash).

Ezeket a bogyókat lehet egyik repoból a másikba átlapátolni a pull-lal.

A bogyók között van összefüggés, hogy melyik bogyó melyik másik bogyóból lett. Ez a history.

A bogyóknak adhatsz ember számára is értelmes nevet, ezek lesznek a branch-ek meg a tag-ek. Ezt a nevet látod a bogyó mellett a historyban. Az, hogy melyik branchen vagy csak annyit jelent, hogy az olyan névvel elnevezett bogyóból indul a history.

Végül a remote branchek a saját repodban csak olvashatók és a legutolsó pull utáni állapotát mutatják annak a reponak ahonnan pulloltál. Ezért van az, hogy ha módosítani akarsz benne bármit, akkor kell csinálnod egy saját branchet belőlük.

 

A git-et Torvalds egy hétvége alatt dobta össze mert szüksége volt rá a melóhoz. Éppen annyi megkötést tartalmaz amennyi feltétlenül szükséges. Azóta ráadásul sokat fejlődött, letisztult, de az alapkoncepció maradt. Mivel éppen ezért bármikor tökönszúrhatod vele magad, érdemes az elején jól megtanulni, hogy mit és hogyan szabad benne csinálni.

Szerkesztve: 2025. 01. 08., sze – 01:18

Ha arról van szó, hogy a távoli módosítás áttekintése miatt nem akarod összefirkálni a munkakönyvtáradat, akkor legjobb egy „git fetch” után nézegetni a távoli ág helyi másolatát - gitk-val (egyszerű GUI, de sokan szeretik), egyéb GUI-val, vagy parancsokkal.

Ha a teljes történet érdekel a távoli repón: például a gitweb egy egyszerű, webes, csak olvasó felület.

A repót lehet klónozni egy másik munkakönyvtárba is, vagy helyben „git worktree” paranccsal új munkakönyvtárat csinálni ugyanarról a projektről.  Ezekben az esetekben ügyelni kell arra, hogy minden szerkesztési műveletnél tudd, melyik munkakönyvtárban lévő fájlt szerkeszted, mert mindenből kettő lesz. :)  Valamint a worktree-s esetben ha ugyanaz az ág van mindkettőbe kicsekkelve, akkor az egyikből rácommit-olva a másikban negatív diff fog megjelenni.  Ez nem kezelhetetlen, de elég zavaró.

> 2. Ha olyan állományt módosítok, ami közben megváltozott, mert más fejlesztő is hozzányúlt, milyen hatékonyságú az összefűzése?

Merge-dzsölésnél lehet konfliktus.  Pl. merge, rebase, pull (ami egy fetch és egy merge) parancsoknál.  A git akkor jelez (és nem fűz össze automatikusan), ha mindkét oldalon ugyanazok a sorok változtak, vagy - emlékeim szerint - a változott soroktól 2 sor távolságon belül változott a másik oldal.

Létezik a szemantikus konfliktus fogalma is - ez nem git-specifikus, akár verziókezelő használata nélkül is.  Ha nem ugyanazok a sorok változtak, azt a verziókezelő nem veszi észre, mégis hibás lesz az összefűzött eredmény.  Ezért minden merge esetén figyelni kell, illetve meggondolni, kell-e egyeztetni a kollégákkal.

Ahogy már írták, be lehet állítani GUI-s merge toolt, de egy idő után jobban szerettem rákeresni a konfliktust jelző „>>>>>>>” jelekre, és szövegszerkesztővel helyrerakni.

> Mivel időközben másik fejlesztő módosíthatott az állományokon, ezért kell egy lépés a 3. pont után, amiben ismételten lehúzom a közös repóból a változásokat, ez elvégzi a változások összefűzését.

Ha tudja, automatikusan.  Ha nem, konfliktust jelez.  Mindkét esetben lehet szemantikai konfliktus (is).

> mi történik, ha a 4. lépés előtt történik a közös repóban egy változás?

Nem enged push-olni, előtte újra pullolni kell.  Ez csak extrém nagy projekteken tud probléma lenni, és nem git-specifikus.

Néhány gondolat még:

Remote repóval kísérletezni még helyi gépen is lehet (van fájlszintű klón).

Az „egymásról pullolunk”-munkafolyamatot nem javasolnám, talán max. 2 emberes csapatra.  Ráadásul ha valaki NAT mögött van, az ő repóját nem lehet megszólítani kívülről.  Jobb, ha van egy közös repó szerveren.

Munkakönyvtáras (nem bare) repóba azért nem push-olunk, mert akkor a konfliktust ott kellene föloldani.  Be lehet állítani azt is, hogy fogadjon push-t, de olyankor a pusholt tartalom negatív diffje fog a célrepóban megjelenni az épp kicsekkelt munkakönyvtárhoz képest, haszna pedig nincs.  A közös repóra nem kell munkakönyvtár.

Rebase: kevésbé kusza történeti gráfot lehet vele csinálni, ez egy darabig vonzott engem, aztán rájöttem, hogy nincs értelme, mindent le lehet kérdezni szövevényes történetből is.  A rebase során viszont macerásabb lehet konfliktust kezelni, és főleg egy hibás rebase parancs eredményét visszalapátolni.

Na, én léptem, látom megjelentek a habzószájú TROLLok, akik még azt is tagadni próbálják, ami pár lépéssel ellenőrizhető lenne.

Kár, hogy ide silányult a HUP, szakemberek helyett csak Rogán-propagandisták rontják itt a levegőt. Ne aggódjatok, hamarosan eljönnek értetek, remélem akkor a HUP is visszanyeri régi fényét!

Mit öcsém, hogy a git úgy működik, ahogy? Azon nincs mit ellenőrizni, mi mind értjük, hogy mi történik, és hogy az nem egy probléma, hanem ilyen a git modellje, és hogy a fájdalmad megoldása az, hogy beírod, hogy git pull --rebase.

Kár, hogy ide silányult a hup, hogy a világ legokosabb fejlesztője annyit nem tud a gitben, hogy 1x1=2. Hosszú évek után.

Kár, hogy ide silányult a hup

Valóban kár. Ha már menni fog neked a magyar nyelvű szövegértés, szólj!

Én továbbra is fenntartom, hogy normális, rendszeres commitolás mellett sokkal egyszerűbb és gyorsabb kézzel azt csinálni lokálban, amit a PR is csinál, semmint bármiféle git paranccsal bohóckodni, de pláne, ha rebase conflicttal elszáll (azt ugye még TROLL uraság nem tudja előre, hogy a git pull --rebase le fog-e futni hiba nélkül avagy sem).

Valóban kár. Ha már menni fog neked a magyar nyelvű szövegértés, szólj!

Mármint hoztál egy móricka példát, hogy márittiszar!!!444. Aztán mikor páran szóltak, hogy de hát ez ilyen, és teljesen triviális a probléma megoldása, akkor elővetted a primadonnát.

Én továbbra is fenntartom, hogy normális, rendszeres commitolás mellett sokkal egyszerűbb és gyorsabb kézzel azt csinálni lokálban, amit a PR is csinál, semmint bármiféle git paranccsal bohóckodni, de pláne, ha rebase conflicttal elszáll (azt ugye még TROLL uraság nem tudja előre, hogy a git pull --rebase le fog-e futni hiba nélkül avagy sem).

Lefordítom: fingod nincs az eszközről, ezért inkább nem használod, aztán sértődötten trollozol, mikor szólnak, hogy hülye vagy.

(ja, nem tudom. Azt tudom, hogy ha megakad, akkor tudom, hogy olyan változás volt, aminek a feloldásával tenni kell valamit. Mert olyan történt azóta, amivel összeakad a jelenlegi alkotásom, szóval rendbeszedem, hogy jó legyen. És ezt meg kellene tenni akkor is, ha kézzel bohóckodol, mert valami nem állt össze azóta. Csak a köcsög tool szólni merészelt róla, meg általában meg is jelöli, hogy A ez, B amaz, mit szeretnél kisgazdám.

A PR meg ha csinál valamit az tudod mi? A végén git parancsokat futtat, amikor be kell mergelni. Addig meg lófaszt se csinál, csak kitesz a webre egy beszélgetőfolyamot. Szóval te pont nem azt csinálod, amit a PR csinálna, mert az rohadtul nem fog újraklónozva kismanókkal fájlokat másolgatni.

Mondjuk eleve nem mintha a példádnak bármi köze lett volna bármilyen pull requesthez, egyszerűen csak a hogyan trackelünk távoli branchet dologról beszéltél.

Nem védem bzt fórumtársat mert a "Rogán-propagandisták" kiszólás az nekem visszatetsző. Nem kellene politikai mederbe terelni egy szakmai témát.

Viszont az is igaz, hogy a git tudott ronda dolgokat elkövetni akár merge-conflict nélkül. Nagyjából 5 éve (+/- 1-2 év) képes volt úgy kezelni commit-ot (vagy push volt már nem emlékszem), hogy simán kifelejtett sorokat, akár 70-80 sort is. Persze szétszórva a kódban mondjuk 1-30 sornyi darabokra szedve. A tesztek persze 90+%-ban elbuktak...
És akkor valának szemek meresztgetése és szájak görbülése lefelé menet. Bizony. Nem 1x.

Ilyenkor bőszen összehasonlítani kellett az eredeti kódot az új kóddal. Akkor derült ki a feledékenység. Lehet, bzt polgártárs erre alapozta véleményét (vagy egyéb hasonló tapasztalatokra), elkövetetve azt a problémát, hogy nem próbálta néhány évvel későbbi változatát a gitnek. Az mondjuk nem mentség az aggreszivitásra/személyeskedésre.

Szerintem a git nagyszerű eszköz hihetetlenül javított a repók használatának/kezelésének élményén. Talán ez most a legjobb.
Aki emlékszik még az rvs, cvs és egyéb tettestársak működésére, valamint a szolgáltatás készletükre és szintakszisukra az csak áldó imák mellett tudja azokat a githez hasonlítani.

Uff! Ja, és punktum.

Még nincs aláírásom.

A git csak egy eszköz, ami rengeteget segíthet egy fejlesztőnek, de végső soron mindig a fejlesztő felelőssége, hogy a repository-k rendben legyenek. Az ilyen problémák mögött sok minden állhat, például hiba a gitben, kollégák bűvészkedése, pluginek, vagy akár valamilyen félreértett workflow.

+1 - Ahogy Te is írtad, én sem cserélném el. Annak ellenére, hogy néha okozhat bosszúságot, a git jelentősen megkönnyíti a munkát, és nehéz lenne visszatérni bármelyik régebbi verzió követő rendszerhez.