---
id: 773766eac9e6ff3c46bd686d78539aed
author: Lemon Mint
title: 'Git Monorepo újragondolása: CAS-Native architektúra emberek és Coding Agents számára'
description: Hogyan építsünk zero-daemon, CAS-natív monorepót standard Git-en, használva a szülő nélküli törzsi pillanatképeket (parentless trunk snapshots), az elkülönített munkaterületi hivatkozásokat (isolated workspace references), a memórián belüli egyesítési fákat (in-memory merge trees), a hierarchikus OWNERS fájlokat, valamint az O(delta) tükörszinkronizációt.
language: hu
date: 2026-10-30T01:17:15.292299Z
path: /blog/posts/rethinking-the-git-monorepo-a-cas-native-architecture-for-humans-and-coding-agents-zfd3d7931
category: lowlevel
---

Minden növekvő mérnöki szervezet előbb-utóbb választani kénytelen a sok tároló és az egyetlen tároló között. Kezdetben dutynyi kis tárolóval egyszerűnek tűnik az élet. Minden könyvtárnak saját hibakövető rendszere, saját CI-folyamata és másodpercek alatt lefutó `git clone` művelete van. Aztán megváltoztatsz egy struktúrát egy központi hálózati csomagban, és a délutánt azzal töltöd, hogy hat downstream tárolóban nyitsz verziófrissítő pull requesteket, miközben a CI-sorok topologikus sorrendben ürülnek ki.

Ha mindent egy hagyományos Git monorepóba költöztetsz, a tárolók közötti koordinációt a tárolóméretért cserélheted el. Ahogy a commit-előzmények mélyülnek, és a bináris eszközök felhalmozódnak a korábbi revíziókban, a `git fetch` lelassul. A munkafák gigabájtos méretűre duzzadnak. Nem telik sok időbe, mire valaki egyedi virtuális fájlrendszer-démont, dedikált kódellenőrző szervert vagy távoli build-munkások flottáját javasolja, csak hogy a napi fejlesztés elviselhető maradjon.

Amikor autonóm kódoló ügynökök csatlakoznak a csapathoz, mindkét hibamód súlyosbodik. A polirepók megvakítják az ügynököt a más projektekből érkező hívókkal szemben, és arra kényszerítik, hogy tárolók között jongláljon a hitelesítő adatokkal. A hagyományos monorepók minden feladat inicializálásakor felemésztik az ügynök konténerének lemezterületét és hálózati sávszélességét, miközben az ugyanazon ágon dolgozó párhuzamos ügynökök végtelen rebase-versenyeket okoznak.

A `google3` architektúrától ihletve egyetlen törzsű (single-trunk) atomi változtatásokat, másodperc alatti ritka (sparse) onboardingot, hierarchikus `OWNERS` irányítást, valamint önálló nyílt forráskódú tükröket építettünk ki szabványos Git-infrastruktúrával és általános célú objektumtárolással.

A tervezés nem igényel sem egyedi fájlrendszer-démont, sem harmadik fél által szállított kódellenőrző készüléket, mert a Git-et Merkle-fa alapú tartalomcímzett tárolóként (Content-Addressable Store, CAS) kezeli.

## A lassú Git monorepók szívében rejlő tévhit

Amikor a fejlesztők panaszkodnak, hogy a Git nem skálázódik nagy monorepókra, ritkán ütköznek a Git objektumadatbázisának korlátjába. A `.git/objects` mappában a Git három megváltoztathatatlan primitívet tárol, amelyeket SHA-1 (vagy SHA-256) tartalomhashük azonosít:

1. **`blob`**: Egyetlen fájl nyers bájttartalma.
2. **`tree`**: Könyvtárlista, amely fájlneveket és jogosultságokat `blob` vagy gyermek `tree` hashekhez rendel.
3. **`commit`**: Apró szöveges fejléc (jellemzően 200 és 300 bájt közötti), amely egyetlen gyökér `tree` hashre, nulla vagy több szülő `commit` hashre és szerzői metaadatokra mutat.

Ha egy monorepo 50 000 fájlt tartalmaz, és egy fájl egyetlen sorát szerkeszted, az új commit a többi 49 999 fájl pontosan ugyanazt a `blob`- és `tree`-hashét használja újra.

A hagyományos Git monorepó azért tűnik nehéznek, mert a konvenció egyetlen hivatkozást, a `refs/heads/main`-t, három egymásnak ellentmondó feladattal terheli:

- Ez tartja a **teljes egyesített könyvtárfát** minden projektről.
- Magával húzza a **teljes szülő-kapcsolt történeti commit-láncot** egészen az első napig.
- A `refs/heads/*` névtérben van, amelyet a Git-szerverek alapértelmezetten hirdetnek, és amelyről alapértelmezetten egyeztetnek minden `git clone` és `git fetch` során.

Valahányszor egy fejlesztő vagy CI-futtató lekéri a `refs/heads/main`-t, a kliens és a szerver több ezer történeti revízión keresztül egyeztetik a commit-gráf elérhetőségét. Ha valaki három évvel ezelőtt véletlenül commitolt egy 100 MB-os archívumot, és másnap törölte, annak `blob`-ja továbbra is egy történeti `tree`-hez kapcsolódik, amely elérhető a `refs/heads/main`-ről.

## A hivatkozási névtér szétválasztása

A Git wire-protokollja szabványos klónozás során csak a `refs/heads/*` és a `refs/tags/*` hivatkozásokat hirdeti. Az egyedi névterekben, például a `refs/trunk/*` vagy a `refs/ws/*` alatt lévő hivatkozások ugyanabban az objektumtárban élnek a szerveren, ugyanazt a packfile delta-tömörítést használják, és kifejezetten lekérhetők vagy feltölthetők, mégsem terhelik az alapértelmezett klónozásokat.

A feladatok különböző hivatkozásokra való szétosztása egyetlen tárolón belül megszünteti a szűk keresztmetszetet:

```
refs/heads/main               Csak vezérlősík (~20 KB: szabályok, .gitconfig, szinkronizációs konfiguráció, szkriptek)
refs/trunk/main               Szülő nélküli pillanatkép-commit, amely a legfrissebb egyesített gyökér fára mutat
refs/trunk/history            Lineáris, szülő-kapcsolt commit-lánc, amely pontosan ugyanazt a gyökér tree SHA-1 hasht használja
refs/ws/<actor>/<id>          Izolált munkaterület-pillanatképek (változáslisták) fejlesztőnként vagy ügynökönként
refs/ws/cl/<change-id>/<tip>  Megváltoztathatatlan patchsetek: a változtatás minden elküldött csúcsa felülvizsgálatra
refs/heads/land/<id>          Átmeneti összefésülési sorkiváltó, amely a beolvasztás után azonnal törlődik
```

### 1. A vezérlősík (`refs/heads/main`)

Az alapértelmezett ág nem tartalmaz alkalmazásforrás-kódot. Csak a tároló működési szabályait (`AGENTS.md`, `README.md`), a munkafolyamat-aliasokat tartalmazó közös `.gitconfig` fájlt, a Starlark szinkronizációs konfigurációt (`sync.star`) és a szerveroldali összefésülési szkripteket követi nyomon. Az alapértelmezett ág klónozása körülbelül 20 KB-ot továbbít, és ezredmásodpercek alatt befejeződik.

### 2. A szülő nélküli törzspillanatkép (`refs/trunk/main`)

A `refs/trunk/main` a teljes szervezet egyesített forrásfájára mutat (`//web/*`, `//net/*`, `//ipc/*`, `//storage/*`, `//crypto/*`, `//ai/*`, `//devtools/*`, `//corp/*`, `//third_party/*`, `//experimental/*`), de commit-objektuma a `-p` szülőjelző nélkül készül.

Mivel a `refs/trunk/main`-nek nincs szülője (`parents = []`), lekéréséhez nincs szükség commit-gráf egyeztetésre. A Git-szerver nem járja be az előzményeket; elküldi az egyetlen fej-commitot és annak aktuális könyvtár-`tree` objektumait. A múlt hónapbeli történeti bináris fájlok vagy törölt fájlok nem érhetők el a `refs/trunk/main`-ről, és soha nem kerülnek átvitelre.

### 3. A lineáris auditelőzmény (`refs/trunk/history`)

A fejlesztőknek továbbra is szükségük van a `git blame` és a `git log` parancsokra regressziók vizsgálatakor. Minden alkalommal, amikor egy változtatás beolvad, az összefésülési szkript két commit-objektumot hoz létre, amelyek pontosan ugyanarra a `$NEW_TREE` gyökér-SHA-1 hashre mutatnak:

```bash
# Szülő nélküli pillanatkép-commit azonnali, mélység-1 munkaterület-lekérésekhez
SNAP=$(git commit-tree "$NEW_TREE" -m "$RAW_MSG")

# Szülő-kapcsolt commit a lineáris git log és git blame parancsokhoz
HIST=$(git commit-tree "$NEW_TREE" -p "$OLD_HIST" -m "$RAW_MSG")

git push --atomic origin \
  --force-with-lease="refs/trunk/main:${OLD_MAIN}" \
  --force-with-lease="refs/trunk/history:${OLD_HIST}" \
  "${SNAP}:refs/trunk/main" \
  "${HIST}:refs/trunk/history"
```

A `refs/trunk/main` és a `refs/trunk/history` megtartása nem duplázza meg a tárhelyigényt. Mivel mindkét commit ugyanarra a `$NEW_TREE` hashre hivatkozik, a Git tartalomcímzett tárolója 100%-ban deduplikálja a `tree` és `blob` objektumokat. A szülő nélküli pillanatkép extra tárhelyköltsége mindössze egy 250 bájtos commit-fejléc.

### 4. Izolált munkaterületek (`refs/ws/<actor>/<id>`)

A folyamatban lévő munkát tartalmazó ágak a `refs/heads/*` helyett a `refs/ws/<actor>/<id>` alá kerülnek. Száz kódoló ügynök percenként menthet ellenőrzőpontokat anélkül, hogy beszennyezné az ágválasztó listákat, vagy lassítaná a `git fetch`műveletet az emberi mérnökök számára.

## Onboarding négy lépésben: a ritka és blob nélküli kijelentkezés működése

Ezzel a hivatkozási elrendezéssel egy új fejlesztőnek vagy egy átmeneti kódoló ügynök konténerének nem kell egyedi CLI-t vagy FUSE-illesztőprogramot telepítenie. Az onboarding négy lépésből áll, szabványos Git-tel és a tároló aliasaival:

```bash
# 1. Klónozás a 20 KB-os vezérlősíkról blob-szűréssel és ritka mód engedélyezésével
git clone --filter=blob:none --sparse https://github.com/example-org/monorepo.git
cd monorepo

# 2. Tárolóaliasok betöltése és a refs/trunk/* csatolása
git config include.path ../.gitconfig
git trunk-init

# 3. A feladathoz szükséges domain-könyvtárak megadása
git sparse-checkout set net/relay ipc/codec

# 4. Izolált munkaterület létrehozása a legfrissebb törzspillanatkép alapján
git ws-new alice/optimize-framing
```

Minden lépés csak azt tölti le, amire szüksége van:

1. A `git clone --filter=blob:none --sparse` letölti a 20 KB-os vezérlősíkot a `refs/heads/main` ágról.
2. A `git trunk-init` beállítja a `+refs/trunk/*:refs/remotes/origin/trunk/*` leképezést, és blob nélküli lekérést futtat. A Git letölti a `refs/trunk/main` `tree` metaadatait (jellemzően néhány tucat kilobájt), és **nulla fájl-blobot**.
3. A `git sparse-checkout set net/relay ipc/codec` utasítja a Git kúpos módú index-szűrőjét, hogy csak a gyökérkönyvtárt és ez a két alfát jelenítse meg.
4. A `git ws-new` új ágra vált, amely az `origin/trunk/main` alapján jön létre. A Git ezután csak igény szerint kéri le a `net/relay` és az `ipc/codec` mappákban lévő `blob` objektumokat. A monorepo fennmaradó 95%-a soha nem kerül a lemezre.

### Jövőbeli kilátás: a `refs/trunk/main` csatolása virtuális fájlrendszerként (VFS)

A ritka kijelentkezés blob nélküli klónokkal extra kliens-eszközök nélkül lefedi a napi munkafolyamatokat. Mivel a `refs/trunk/main` már tiszta Merkle-fa egy tartalomcímzett tárolóban, az architektúra közvetlen alapot nyújt egy opcionális felhasználói térbeli virtuális fájlrendszerhez (VFS), amely Linuxon FUSE-n, macOS-en FileProvideren, Windowson pedig ProjFS-en keresztül valósulhat meg:

1. **Azonnali teljes fa csatolás**: Egy könnyű helyi csatolási démon beolvassa a `refs/trunk/main` gyökér `tree` objektumát, és ezredmásodpercek alatt levetíti a teljes monorepo könyvtárhierarchiát a munkakönyvtárba, így nincs szükség a `git sparse-checkout set` futtatására.
2. **Igény szerinti blob-betöltés**: A fájltartalmak virtuálisak maradnak mindaddig, amíg egy fordító, IDE vagy ügynök nem ad ki `open(2)` vagy `read(2)` rendszerhívást. A démon ekkor lekéri a megfelelő SHA-1 `blob`-ot a CAS végpontról, és helyben, NVMe tárolón gyorsítótárazza.
3. **Copy-on-Write átfedés a munkaterületekhez**: A helyi szerkesztések egy könnyű felső átfedési rétegbe íródnak. A `git ws-save` futtatása csak az átfedés módosított útvonalait hashelei, kiírja a frissített `blob` és `tree` objektumokat, és a keletkező commitot feltölti a `refs/ws/<actor>/<id>` alá, anélkül hogy a változatlan könyvtárakat végigpásztázná.

## A változáslista-modell tiszta Git-en: memóriabeli landolás szerveroldalon

Egy hagyományos Git-munkafolyamatban egy funkcióág beolvasztása vagy két szülős összefésülési commitot hoz létre, ami nem lineárissá teszi az előzményeket, vagy kézi rebase-et igényel, és versenyt kell futtatni a `main` ágra érkező párhuzamos feltöltésekkel.

A `google3` Changelist (CL) modelltől ihletve architektúránkban minden munkaterület egyetlen atomi változást jelent a törzspillanatképhez képest. Amíg a fejlesztő vagy ügynök a `ws/alice/optimize-framing` munkaterületen dolgozik, tíz inkrementális commitot készíthet (`wip`, `fix tests`, `lint`). Amikor a változtatás készen áll a beolvasztásra, a szerver a munkaterület-deltát egyetlen lineáris törzsrevízióba tömöríti anélkül, hogy a CI-futtatón bármilyen munkakönyvtárat kijelentkeztetne.

Így fut a landoló szkript (`land.sh`) memóriában a Git 2.40+ alacsony szintű parancsaival:

```bash
# 1. Annak a gyökér-pillanatkép commitnak az azonosítása, ahonnan a munkaterület elágazott
BASE=$(git rev-list --max-parents=0 "$WORK_SHA")

BASE_TREE=$(git rev-parse "${BASE}^{tree}")
MAIN_TREE=$(git rev-parse "${OLD_MAIN}^{tree}")
WORK_TREE=$(git rev-parse "${WORK_SHA}^{tree}")

# 2. Az összefésült gyökérfa kiszámítása memóriában, munkafa-kijelentkezés nélkül
if [ "$MAIN_TREE" = "$BASE_TREE" ]; then
  NEW_TREE="$WORK_TREE"
elif OUT=$(git merge-tree --write-tree --merge-base="$BASE_TREE" "$MAIN_TREE" "$WORK_TREE"); then
  NEW_TREE=$(head -n1 <<<"$OUT")
else
  echo "Merge conflict detected; run git ws-sync to rebase." >&2
  exit 1
fi
```

A 2. lépésben:

- Függetlenül attól, hány helyi commit készült a munkaterület ágán, a szkript csak három tree hasht hasonlít össze: az eredeti alappillanatképet (`$BASE_TREE`), az aktuális törzspillanatképet (`$MAIN_TREE`) és a végső munkaterület-fát (`$WORK_TREE`).
- Ha a `refs/trunk/main` előrelépett a `//web/blog` alatt, miközben Alice a `//net/relay` részt szerkesztette, a `git merge-tree --write-tree` ezredmásodpercek alatt kiszámítja a kombinált gyökérfát, a `$NEW_TREE`-t, közvetlenül a Git objektumtárában, anélkül hogy fájlokat írna a futtató fájlrendszerére.
- Miután az alábbi szabályzati ellenőrzések átmennek, egyetlen `git push --atomic` `--force-with-lease` kapcsolóval frissíti a `refs/trunk/main`-t, egy lineáris commitot fűz a `refs/trunk/history`-hoz, és a `refs/heads/land/<id>` landoló kiváltó törlődik.

## Az architektúra-határok kikényszerítése: négyszintű láthatóság és hierarchikus `OWNERS`

A kód egyetlen tárolóba konszolidálása csak akkor működik, ha a domainek közötti határokat gépiesen kikényszerítik, mielőtt egy commit beolvadhatna. Közvetlenül azután, hogy a `git merge-tree --write-tree` előállítja a `$NEW_TREE`-t (és mielőtt a `git push --atomic` frissítené a törzset), szabályzatmotorunk két O(delta) ellenőrzést futtat a `git diff-tree "$MAIN_TREE" "$NEW_TREE"` kimenetén.

### 1. Négyszintű domain-láthatóság

A gyökérfát négy láthatósági szintre osztjuk:

| Könyvtár-előtag                                                                        | Szint                | Engedélyezett importok                              | Tiltott importok                    | `OWNERS` kapu          |
| :------------------------------------------------------------------------------------- | :------------------- | :-------------------------------------------------- | :---------------------------------- | :--------------------- |
| `//web/*`, `//net/*`, `//ipc/*`, `//storage/*`, `//crypto/*`, `//ai/*`, `//devtools/*` | Nyilvános éles       | Nyilvános éles, `//third_party/*`                   | `//corp/*`, `//experimental/*`      | Kényszerített          |
| `//third_party/*`                                                                      | Külső szállító       | Önálló vagy `//third_party/*`                       | Minden nem `third_party` domain     | Kényszerített          |
| `//corp/*`                                                                             | Belső, zárt          | Nyilvános éles, `//corp/*`, `//third_party/*`       | `//experimental/*`                  | Kényszerített          |
| `//experimental/<actor>/*`                                                             | Homokozó             | Bármely nem `corp` csomag                           | `//corp/*`                          | Mentesített (automatikusan jóváhagyott) |

Ha a `//web/*` egyik nyilvános csomagja egy `//corp/*` belső csomagot vagy a `//experimental/*` alatti, még át nem vett prototípust próbál importálni, a landoló feladat megszakad, mielőtt hozzányúlna a `refs/trunk/main`-hez.

### 2. Hierarchikus `OWNERS` ellenőrzés Gerrit-szerver nélkül

Az ellenőrző a könyvtárszintű `OWNERS` fájlokat öröklési szabályokkal kényszeríti ki:

- A `$MAIN_TREE` és a `$NEW_TREE` között módosított minden útvonalnál az ellenőrző a fájl könyvtárától felfelé halad a `//OWNERS` fájlig.
- Bármely `OWNERS` fájl deklarálhatja a `set noparent` utasítást, amely megakadályozza a szülőkönyvtárakból öröklött jóváhagyásokat, vagy a `per-file *.sql=@dba-team` utasítást, amely a jóváhagyásokat fájlnév-minta szerint szűkíti.
- **Manipulációvédelmi invariáns**: A meglévő `OWNERS` fájlokat mindig a `$MAIN_TREE`-ből (az aktuális törzsfából) olvassuk, soha nem a `$NEW_TREE`-ből. Egy jogosulatlan szerző nem adhat magának engedélyt úgy, hogy ugyanabban a munkaterület-commitban módosítja az `OWNERS` fájlt.
- **Homokozó-mentesség**: A `//experimental/<actor>/*` alatti útvonalak megkerülik az `OWNERS` ellenőrzéseket, így a mérnökök és ügynökök szabadon prototipizálhatnak a `git ws-exp <actor> <project>` paranccsal, később pedig a `git ws-graduate` paranccsal átemelhetik a csomagot éles domainbe.

## Kódellenőrzés súrlódás nélkül: átmeneti PR-ek és pillanatkép-diffek

Mivel a `refs/heads/main` csak a vezérlősíkot tartalmazza, a `refs/trunk/main` pedig szülő nélküli commit, egy szabványos GitHub Pull Request megnyitása közvetlenül a munkaterület ágából a `main` ágba összeálíthatatlan történetek összehasonlítását kísérelné meg. Ezt három, a változások típusához igazított felülvizsgálati munkafolyamattal oldottuk meg:

1. **Azonnali kétpontos munkaterület-diffek (`git ws-save` + élszintű diff-útválasztó)**
   A `git ws-save` paranccsal feltöltött munkaterület a `refs/ws/<actor>/<id>` hivatkozást egy könnyű élszintű munkavégző felé teszi elérhetővé. Ez a munkavégző a `refs/trunk/main`-t és a munkaterület-hivatkozást commit SHA-kra oldja fel, majd átirányít a GitHub kétpontos összehasonlító nézetére (`/compare/<trunk-sha>..<ws-sha>`). Kisméretű foltok vagy ügynökök által generált változtatások esetén a felülvizsgálók megvizsgálhatják a diffet, és közvetlenül a webes felületen a **Land** gombra kattinthatnak.
2. **Átmeneti GitHub Pull Requestek (`git ws-pr`)**
   A soronkénti GitHub-os felülvizsgálathoz a `git ws-pr` feltölti a gyökér-pillanatkép commitot (`$(git rev-list --max-parents=0 HEAD)`) a `refs/heads/base/<id>` alá, a munkaterület csúcsát pedig a `refs/heads/review/<id>` alá. Ezután GitHub Pull Requestet nyit, amely a `review/<id>`-t a `base/<id>`-hez hasonlítja. Mivel az alapág az a pillanatkép, amelyből a munkaterület elágazott, a GitHub **Files changed** fülén csak a munkaterület-delta látszik. Amikor a felülvizsgáló a **Merge pull request** gombra kattint, egy webhook előlépteti a fej-commitot a `refs/heads/land/<id>` alá, lefuttatja a memóriabeli landoló folyamatot, és automatikusan törli mind a `refs/heads/base/<id>`, mind a `refs/heads/review/<id>` hivatkozást.
3. **Külső tükör-pull requestek**
   A nyílt forráskódú közreműködőknek soha nem kell megtanulniuk a monorepo munkafolyamatát. Szokásos módon forkolnak, és pull requesteket nyitnak az önálló tükör-tárolókhoz.

### Változások, patchsetek és jóváhagyások átvitele

Egy ágnév nem azonosíthat egy változtatást. Egy ügynök átnevezheti az ágát, módosíthatja a csúcsot, vagy többször rebase-elhet egy újabb törzsre a beolvasztás előtt. A Gerrithez hasonlóan a munkafolyamat a változtatást a csúcs commit üzenetében található `Change-Id: I<40 hex>` záradékkal azonosítja. A `git ws-save`, a `git ws-pr` és a `git ws-land` hozzáadja a záradékot, ha a csúcsban nincs, egyébként megtartja, így az azonosító túléli a módosításokat, rebase-eket és átnevezéseket. A beolvasztott törzs-commit megtartja a záradékot, és rögzíti a hozzá tartozó felülvizsgálati pull request számát, így a `git trunk-cl <number|Change-Id>` megtalálja a `refs/trunk/history`-ban.

Minden felülvizsgálatra küldött csúcs patchsetté válik. A `git ws-pr` a megváltoztathatatlan `refs/ws/cl/<change-id>/<tip>` hivatkozásra tölti fel a felülvizsgálati ágak mellett. Ha a `git ws-pr` futtatása módosítás vagy `git ws-sync` után ismétlődik, a patchset ugyanahhoz a pull requesthez adódik hozzá. A `git ws-ps` listázza az aktuális változás patchsetjeit, a `git ws-psdiff <a> <b>` pedig kiírja a két patchset közötti interdiffet, így a felülvizsgáló csak az utolsó kör óta változott részeket olvassa el.

A GitHub a jóváhagyást egyetlen commithoz köti, ezért minden rebase általában új felülvizsgálatot igényelne. A landoló folyamat elfogad olyan jóváhagyást is, amelyet ugyanazon változás egy másik patchsetjére adtak, ha mindkét patchset ugyanazt a foltot alkalmazza a saját alappillanatképére. Ehhez a `git patch-id --verbatim` parancsot hasonlítja össze a teljes bináris diffen. Egy tiszta rebase egy újabb törzsre újabb felülvizsgálat nélkül beolvad, míg bármilyen tartalmi szerkesztés, beleértve a szóköz- vagy fájlmódváltozást is, új jóváhagyást igényel.

## O(delta) kétirányú szinkronizáció és külön éles ágak

Sok szervezet az egyes csomagokat önálló GitHub-tárolóként teszi közzé, hogy a külső felhasználók a monorepo érintése nélkül `go get`-et, `cargo install`-t vagy egyetlen projekt forkolását végezhessék el. Egyes projektek, például a statikus blogok vagy a kiadáshoz kötött webalkalmazások, a `main` mellett külön `production` ágat is fenntartanak.

Starlark szinkronizációs motorunk mind a kimenő exportokat, mind a bejövő hozzájárulásokat O(delta) idő alatt kezeli, amely a commitban módosult fájlok számával arányos, nem pedig a monorepo méretével:

- **Blob nélküli index-összefűzés**: Amikor egy tükör-tároló részfáját a monorepo gyökérfájába illesztjük be, vagy onnan kiemeljük, a motor beállítja a `GIT_NO_LAZY_FETCH=1` változót, majd lefuttatja a `git update-index --index-info` parancsot, utána pedig a `git write-tree --missing-ok` parancsot. A nem módosított részfák és blobok SHA-1 hivatkozással maradnak, és soha nem töltődnek le a CI-futtatóra.
- **Csak a delta blobjainak előzetes lekérése**: Mielőtt egy exportált commitot egy önálló tükörre feltöltenénk, a szkript lefuttatja a `git diff-tree -r --diff-filter=AM "$ext_parent" "$export_tree"` parancsot, és a `git cat-file --batch` segítségével csak a módosított fájlok régi és új blobjait tölti le előre. A Git ezután vékony deltacsomagot tud számolni, és másodpercek alatt feltölteni a tükör-tárolóba.
- **Munkafolyamat- és kiadási ágak megőrzése**: Kimenő export során a szinkronizáló minden önálló tároló saját `.github/workflows/` könyvtárát megőrzi, így a nyilvános CI-futtatók a tükrön futtatják a projekt teszteit. A Starlark konfigurációban minden munkafolyamat egy explicit ágat céloz meg, például a `main`-t, ami megőrzi a kiadási kapukat azoknál a tárolóknál, amelyek külön `production` ágról telepítenek. A monorepo beolvasztásai a tükör `main` ágával szinkronizálnak, a `main` ágon automatikusan létrejövő metaadat- vagy fordítási commitok pedig webhookon keresztül visszaszinkronizálódnak a `refs/trunk/main`-be. A `main` `production` ágra léptetése továbbra is explicit kiadási lépés marad.

## Záró gondolatok

Ez az architektúra a Git objektumtárát tartalomcímzett tárolóként kezeli, szétválasztja a `refs/heads/main`-t a `refs/trunk/main`-től és a `refs/trunk/history`-tól, minden változtatást `Change-Id` azonosítóval és megváltoztathatatlan patchsetekkel különít el, és a fákat memóriában egyesíti a `git merge-tree --write-tree` paranccsal. Az onboarding költsége azzal a könyvtármérettel nő, amelyre egy feladatnak szüksége van, a landolás és a tükör-szinkronizáció költsége pedig a változtatás méretével, nem pedig a tároló méretével.
