A földkerekség legnagyobb Git tárolója

Februárban jelentette be a Microsoft, hogy Git-re áll át és annak segítségével folytatja a Windows termékvonal fejlesztését is. Brian Harry most egy helyzetjelentést adott közre arról, hogy hol tartanak és mi vár rájuk a közeljövőben.

A blogbejegyzés itt olvasható.

Hozzászólások

azt hittem visual sourcesafebe (vagy hogy a rákba hívják) nyomják, mi törpént, megvilágosodtak lol...

--
GPLv3-as hozzászólás.

Miért van olyan érzésem, hogy rosszul használnak egy eszközt? :)

Ahja, a mindent-bele repó az, ami nekem nagyon-nagyon furcsa, nem létezik, hogy az összes projektjük között forrásszintű mozgásra lenne szükség. Az, hogy egy olyan eszközt használnak olyan célra, amire az nem való, mert a teljes repót leszedi minden történésével, majd ezt körbetákolják, hogy egyáltalán működjön, az is furcsa. Nem mondtam, hogy hülyék dolgoznak ott, de nem ez lenne egyiknél se az első hülye döntés... :)

Miért van az a forrásrészlet több projektben _másolva_? Ezt a helyzetet nem a verziókezelő tákolásával kell megoldani, ez annál mélyebb probléma, ha ez az oka.

Továbbra se látom annak értelmét, hogy _minden_ egyes projekt egy repóba kerüljön... sarkítva: mi indokolja, hogy egy gépi kódon megírt firmware és egy JavaScript fájl egy repóban legyen?

Csak egy példa:
Continuous Build/Delivery:

Van egy alkalmazásgyűjteményem A,B,C,D komponensekkel, amik ebben a sorrendben függenek egymástól.
Egyik komponensen (legyen B) készítek egy feature branchet. Commit-olok bele.
Mit és mikor build-elek le a teljes rendszer teszteléséhez? (Lehet, hogy ez után a commit után egy másik komponensben is fogok valamit változtatni, pl. API változás miatt.)
Pontosabban melyik komponens melyik branch-ét?

Ha egy repository van, akkor nincs ilyen kérdés, mert a branch az összes komponenst érinti. Ez nagyon kellemes lehet, ha komponenseken átívelő változtatásokat kell eszközölni...

Épp elég, ha van egy rakás összefüggés mindenütt - ahogy tuti, hogy van. Ha egyben van minden, akkor ezeket az eseteket nagyon jól lehet kezelni minimális erőfeszítéssel. Ha nincsenek, akkor a managerek egyfolytában olyan vitákon ülnek napokat, ahova elhívnak 1-1 fejlesztőt az összes érintett csapatból, és azon vitáznak, hogy melyik csapatnak az infrastruktúráján ki nyithat feature branchet és ki nem.

Ilyeneken olyan megoldások szoktak születni, hogy:

* A csapat kiadja a kódot, miután tesztelte a saját környezetében, és aztán B, C D és E csapatok integrálják. Ha 1 csellentyűcske nem működik, akkor change request, patch version, all hell broke loose
* A csapat csinál egy mirrort magának a B csapat verziókezelőjéből és B csapat csinál egy mirrort A csapat verziókezelőjéből, mert azért bele kell peccselgetniük, de ezt szigorúan nem képesek megosztani egymással valami IT faszkodás miatt.
* A csapat megelégeli a végtelen meetingeket és felteszi a toldacuccot.hu-ra a peccset és magán emilen elküldi a linket a B csapatnak, akik pendrájvon becsempészik a cégbe, mert az IT és a menedzserek hetek óta azon pingpongoznak, hogy hogy kellene megosztani a projektet a két csapat között :-).

Most arról beszélsz, amikor külön repókban vannak, de erős függésben vannak egymással, ahelyett, hogy egy vékony API-n keresztül függenének, és a forrásaiknak semmi közük nem lenne egymáshoz.

Megoldás 1: szüntessük meg az erős függéseket.
Megoldás 2: rakjunk mindent egy repóba (alább írtam, hogy ez miért nem szerencsés).

Szüntessük meg az erős függéseket -> valósítsuk meg ugyanazt 10 helyen. Vékony API legyen -> hónapos meetingsorozat az API-ról, hogy olyan legyen ami mindenkinek elfogadható. Egyetlen új metódus felvétele több hónapig tart a kommunikációs körök és a csapatok beosztási problémái miatt. Addig áll az új funkció fejlesztése.

Szüntessük meg az erős függéseket -> valósítsuk meg ugyanazt 10 helyen.

Ezt még mindig nem értem, hogy ez miért függ össze. Miért kellene ugyanazt 10 helyen megvalósítani, miért nem egy lib-ben, amit 10 helyen is használnak?

Vékony API legyen -> hónapos meetingsorozat az API-ról, hogy olyan legyen ami mindenkinek elfogadható.

Ezt sem igazán értem, hogy a tervezés az miért csapatok közötti, hónapos meetingek sorozata.
Azt sem látom be, hogy tervezés helyett jobb az, ha bárki beírhat bárhová, bármit, mert lehetősége van rá.

Kerdes, hogy miert lenne kulon. (Valojaban azert szoktunk kulon repokat hasznalni, mert a toolok ugy vannak kialakitva, hogy azt feltetelezik, hogy a repo az egy alkalmazasnak/rendszernek felel meg.)

Nezd meg, hogy pl. a 'go get github.com/user/projekt' hogy mukodik. Kicsit hasonloan, mint a Maven central, csak a github a tarolo. A Maven central-t reponak szokas hivni -- ebben az ertelmezesben a github is egy repo.

Szoval semmi gond azzal, ha 'minden egyben' van, ha van extra struktura.

----------------------
while (!sleep) sheep++;

Ha így értelmezed a monorepót azzal csak az a gond, hogy elveszti az összes jónak gondolt előnyét:
1.) Több eszközzel és egyszerűbben használható, mivel ott van minden egy fájlstruktúrában (pl. grep-es keresés) és nem kell az egyes részek verzióival törődni.
2.) Nem kell verziózni az egyes részeket, minden egy közös verzión van.
3.) Könnyen lehet egyben (egy branchben) kezelni a projekteken átnyúló változtatásokat.
4.) Nem kell foglalkozni a függőségekkel.

Én ezeket egyáltalán nem tartom előnyöknek, lásd a részletes írásomat.

"Valojaban azert szoktunk kulon repokat hasznalni, mert a toolok ugy vannak kialakitva, hogy azt feltetelezik, hogy a repo az egy alkalmazasnak/rendszernek felel meg."

Szerintem azért szoktunk külön repókat használni, mert a mosógép szivattyújának 8 bites processzoron futó vezérlő szoftverének a módosítása feleslegesen lenne a nagy közösben együtt egy changeset alatt a Firefox magyar nyelvű fordításnak javításával. És akkor nem beszéltünk a jogosultságokról és a többi úri huncutságról.

"Nezd meg, hogy pl. a 'go get github.com/user/projekt' hogy mukodik."

Külön-külön projekt külön-külön repóként. Nem tudok egy changeset alatt feltolni két külön projektbe módosításokat. Biztos értjük, hogy mit beszélünk egymással?

"Szoval semmi gond azzal, ha 'minden egyben' van, ha van extra struktura."

Ugye a tárgybeli esetben pont az a helyzet, hogy nincs extra struktúra. Ha full feature Git kell a fejlesztőnél, akkor le kell hozni több száz GB adatot, minden szart, minden befulladt projektet a világ kezdetétől mostanáig, ezért GVFS nélkül egy clone 12 órás művelet volt. 12 órás művelet! Ezt sikerült leszorítani 5 percre GVFS-el. Egy clone-t!

Értem én, hogy ez csodálatos dolog és azt is értem, hogy bele kellett harapni valamelyik ujjukba, mert valószínűleg egy, azaz egy repó hízott meg ennyire hosszú évek és évtizedek alatt, amelyben most már csak kurva keservesen lehetne szétvágni a tekergőző csápokat és erre nincs idő a kiélezett piaci helyzetben... de ettől még ne tegyük a kirakatba úgy, mint ultimate megoldást, amikor ez csak az évek alatt felhalmozott technical debt halomra egy workaround... Ássunk egy gödröt, amibe berakhatjuk azt a földet! :)

"Mit és mikor build-elek le a teljes rendszer teszteléséhez?"
Ehhez azt kell pontosan tudnod, hogy mi éppen a teljes rendszer definíciója, hogy mely bináris artifactokból áll. Csak ez dönti el, hogy mit kell buildelned ahhoz, hogy a teljes rendszer előálljon.

A teljes rendszer definíciója ugyanis megmondja, hogy mely komponensek pontosan melyik verziói alkotják a teljes rendszert.

És ez totálisan független attól, hogy a "teljes rendszer" komponenseit monorepoban vagy nem monorepoban tárolod. Sőt, az se biztos, hogy a "teljes rendszer" minden forráskódját te tárolod, sok esetben csak a bináris artifacthoz férsz csak hozzá. Attól még a teljes rendszer definíciójának meg kell lennie.

Kényelmesnek tűnik, de nem az, ráadásul pont a Continuous Delivery -t lehetetleníti el.

Tegyük fel, hogy van egy A komponensed, amitől függ a B, C, D komponens.
A komponensen API változtatást végzel egy branch-ben, emiatt nem fog fordulni a B, C, D komponensed sem ugyanabban a branchben. Milyen jónak tűnik!
A gond akkor kezdődik, ha a B komponensnél szeretnéd ezt a változást minél gyorsabban lekezelni és kiküldeni (delivery) az új B komponens-t, legyen ez 2 nap. Csakhogy ezt nem tudják megtenni, amíg a C, D komponensekben is át nem vezetik a változást. A C komponensben éppen egy sürgős funkciót raknak, amit egy hét múlva kellene küldeniük.
Ilyenkor az a helyzet áll elő, hogy vagy a C komponens készítők abbahagyják a munkájukat és átvezetik az A változásait 2 nap alatt, hogy kimehessen a B, de akkor két napot csúsznak, vagy megcsinálják a saját funkciójukat, majd aztán vezetik át a változásokat, akkor meg a B fog csúszni egy hetet.

Egy gigászi monorepóban mérhetetlen sok ilyen függőség lesz. Egyik komponens változása magával ragad egy csomó másik komponenst, egyik vár a másikra, majd fél évente, ha minden lecsitul, akkor ki lehet adni minden komponensből egy verziót, ami ezer módosítást tartalmaz.

Ezzel szemben, ha szépen el vannak szeparálva az egyes komponensek, akkor az A változása nincs hatása senkire, akár egyből lehet küldeni. B, az új A alapján átvezetheti a változásait, majd tesztek és build után mehet azonnal ki. Ha bármi probléma van, akkor lehet tudni, hogy mivel van, hiszen csak nagyon kicsi változások után mennek ki az új verziók. Emellett C, D komponensek is élik a saját életüket, nincsenek egymással összekötve. Pl. a B2.4 az A1.3-at használja, majd a B2.5-ben az A2.0-ra állnak át. Semmi más változtatás nincs, mehet ki. Miközben C3.5 már az A1.7-et használja, de az A2.x-re váltás még nem sürgős nekik, előbb a saját szolgáltatásaikon fejlesztenének.

A munka is kevesebb lesz összességében, hiszen A minden egyes változását nem kell átvezetni a B, C, D-n minden egyes alkalommal, nem kell új teszteket írni, a meglevőket futtatni, kézzel tesztelni, kiküldeni. Egy-egy változtatás, mint tudjuk, hibalehetőségeket rejt magában, így az összes tőle függő komponenst (nem csak a közvetlen függőeket) érintheti.

A munka is könnyebb a szeparált esetben, mivel az A komponensnél nem lesznek ott a B, C, D komponens branch-ei, csak a sajátjai.

Attól, hogy egy repód van, még megmarad a függőségek kezelésének kényszere, azt ugyanis nem a repók száma, hanem a kód, illetve a megoldandó feladatok komplexitása szüli.
Az egy repóval a függőségkezelés csupán az egyszerű esetekre válik triviálissá (nem kell csinálni semmit), a bonyolult esetekre viszont megnehezül. Vannak más dimenziói is a problémának, pl. első kellemetlen következmény, hogy a "fejlesztői közösség" jórészt nem fog tudomást venni a probléma létezéséről, hiszen az egy repos megoldás elrejti a kérdéskört. Ha sok repod van, akkor nem tudsz meglenni jó API definíciók nélkül, és rá vagy kényszerítve, hogy gondolkodj a függőségeken.
Gondolom a redmondi fiuk végiggondolták a dolgot, (pl. ha sok szarul definiált moduljuk van, öngyilkosság belefojtani a függőségkezelés gyötrelmeibe a fejlesztést), és a számukra optimális verziót választottak.

miért van egy olyan érzésem, hogy ez a monorepo olyan, mint a big data... azaz hánnyunk mindent egybe, aztán nevezzük külön szakterületnek azt, hogy próbáljuk valami értelmesre használni ;)

Mondjuk róluk mondta Barnacules, hogy bár ki kell adni a forrásokat mindenféle nagy kormányok szolgálatainak, de olyan bonyolult buildrendszere van, hogy más úgysem tudja reprodukálni :D

Nem igazán az adatbázis típusa érdekelt, hiszen akár relációs adatbázisba is bele lehet rakni mindenféle adatot, inkább olyan cégekre, akik minden adatukat egy adatbázisba teszik és sikeresek (legalábbis én így értettem a kijelentésedet).

Nem, az internet nem egy adatbazis. Semmilyen szemszomgbol.

Ez csak attól függ, hogy miként definiálod az adatbázist. Az általam ismert definíciók szerint az.
Wikipedia: Database
The World Wide Web is thus a large distributed hypertext database.

World's Largest Database: The Web of Data

RDBMS alapbol szeirntem sokkal behataroltabb. Eleg kuzdelmes skalazni egy keneralis datastore-hoz kepest. Nem tudom, ki teszi minden adatat egy adatbazisba, gondolom senki? Nem is lenne logikus. Nem is mondta senki, hogy barki ilyet tenne.

Nem ertek egyet a wikipediaval :) Nem gond, ugye?

Gondolnam, hogy az indexeles, kereses, sebesseg, kereszthivatkozasok, adatmennyiseg, egy-egy nagy metaadat eltarolasa annyira nem kedvez sehol, minden adat egybe rakasanak. Nem vagyok adatbazisguru, de nem lennek biztos benne, hogy minden nagy ceg megosztja, mikor mire, mit, mennyi adatot tarol. Igy azert kicsit nehez tippelni, hol tarolnak DB-ben legnagyobb adatot.

Mit szeretnel mondani? Hogy a NoSQL, amit adnak gyenge? Lassu? Vagy hogy megszabjak, mit pakolsz bele? Vagy nincs benne sok adat? En ugy ertelmeztem - a rendelkezesre allo adatokbol - hogy ez egy altalanos, igen nagy adatbazis. Hogy konkretan mi van benne, es mennyi adat, azt csak tippelem, hogy sok. Ennyi, nem tobb.

Innen indultunk: "Én nem tudok ultimate all-in adatbázisról, melyik az, amelyik _mindenre_ egyformán jó?"

A Bigtable messze nem ilyen, vannak olyan esetek, amire kiváló, vannak olyan esetek, amire a kategóriájában vannak jobbak, kategóriáján kívüli feladatokra meg meg alkalmatlan.

Hogyne merülne fel, sőt azt gondolom, hogy ez így is történt! Sőt úgy tudom, hogy a Google és a Facebook háza táján is vannak ilyenek.

Évekig, évtizedekig lapátolták össze a kódokat egy hatalmas monolitba, majd, amikor már kezelhetetlen méreteket ölt, akkor választhatnak, hogy vagy évekig bontogatják kisebb részekre, úgy, hogy közben a fejlesztési metodikán is alaposan változtatni kell, ami érint rengeteg dolgozót; vagy pár hónapos, pár fejlesztőt érintő munkával az eszközeiken módosítanak. Logikus, hogy az utóbbi mellett döntenek, de ettől nem lesz jó az, ahogyan csinálják.

Ez csak az én személyes véleményem, aki ennek ellenkezőjét gondolja, azt is tiszteletben tartom!

Az MS-t es a Facebookot nem ismerem ilyen szempontbol, de a Google eseteben cseppet sem arrol van szo, hogy egy nagy monolitjuk van. (Hogyismondjam -- nem vagyok egy Google-fan, finoman szolva, de az o skalajukon abszolut van ertelme pl. a monoreponak, es _nagyon_ jol mukodik a dolog. A monoreponak es a monolitnak semmi koze egymashoz.)

----------------------
while (!sleep) sheep++;

Ha mar kezelhetetlen, akkor irnak egy verziokezelot ami tudja kezelni:

https://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions…

"Google relied on one primary Perforce instance, hosted on a single machine, coupled with custom caching infrastructure1 for more than 10 years prior to the launch of Piper. Continued scaling of the Google repository was the main motivation for developing Piper."