Games in their own repositories: separating Hydro from its first game
Hydro, its editor and its first game all lived in one repository. The plan to give every game its own repo, the 16 couplings in the way, and the first five steps.
Until now, Hydro, the Oxygen editor and Eonlore, the tactical RPG I'm building on it, all lived in one repository. The game's project sat inside the editor's folder: 234 MB in 6,795 files. That was convenient for a while, but it means the engine can't be cloned without the game, a second game has nowhere to go, and nobody can tell where the engine ends and the game begins.
The goal of the current pull request: a game lives in its own git repository, and the engine, editor and player know nothing about any one game. Oxygen opens or creates a project from any folder, through a project hub.
Defining "done" first
Before any code, the plan has a success test of five steps:
- Clone the engine alone and build it. Oxygen starts from its exe, from any working directory, and shows the project hub.
- New Project in a scratch folder creates a project that opens, saves and plays.
- Clone the game repo next to the engine and build its workspace. Its Oxygen opens the game and the Shrine Glade plays.
- File › Build writes a package into the game's own folder, and the package still runs with the engine checkout renamed.
- Nothing in the engine repo changed while doing 2–4.
Sixteen couplings
Then I listed every place where the engine assumed the game, checked against the code. Some examples:
- Engine shaders were loaded by paths relative to the working directory, and lived in the editor's folder. Oxygen only worked when started from that exact folder.
- Editor settings and the docking layout were found from the working directory, and tracked in git.
- The game code was a fixed library linked into every Oxygen and Runtime build.
- All 36 build-script paths were relative to the solution, so the engine couldn't be included from another repo.
- And one surprise: Debug CI was red on main, because the generated reflection code exceeded the object file's section limit. That became step zero.
The decisions that matter
Workspace and project are different things
A workspace is the build environment of one game: its solution, its C++ code, its build scripts. A project is the content the editor opens: scenes, prefabs, data. Each game repo is a workspace with one project inside. The workspace is described in one JSON file that premake, Python, the batch scripts and CI can all read.
Which engine version does a game need?
The engine is checked out next to the game, and an engine.lock file names the Hydro commit the game expects. Locally a mismatch only warns, because engine and game are often changed together. In CI it fails, because CI checks out exactly that commit.
Opening the wrong game's project must be safe
I checked what the serializers do with types they don't know. Unknown script values and unknown data fields are kept and written back, but an unregistered component is dropped on save. So editing a project with another game's editor would silently destroy content.
That decided it: every project carries a stable game ID. Opening another game's project offers Open read-only, Locate the right editor… or Cancel, and there's no "continue anyway" until unknown components survive a round trip.
Resources travel with the exe
Every build copies the engine's shaders next to its exe, so a package never depends on the source checkout. Only Oxygen's Debug and Release builds may load from the source folders, so shader hot reload still edits the real files.
Rehearse, then split, and keep the history
The game first moves to Projects/Eonlore/ inside the engine repo, and the success test runs there. Only then is it split out with git filter-repo, following a map of every path game material has ever lived at. Nothing is deleted from the engine until git log --follow and git blame show pre-split history on four sample files: a scene, a script, a tool and a doc.
No Git LFS, decided from data
The whole repository pack is 245 MB and the largest file is 5.8 MB. LFS wouldn't change clone sizes meaningfully and adds tooling, so it's not worth it yet. Blender backup files get ignored and dropped from the extracted history instead.
Where it stands
| Step | Status |
|---|---|
S0 Fix Debug CI (/bigobj) | Done |
| S1 Engine paths, shaders staged beside every exe | Done |
| S2 Editor settings per user, out of git | Done |
| S3 Project hub and recent projects | Done |
| S4 The game as a parameter of the workspace, read-only for other games | Done |
| Engine-owned test bed (Sample) | Next |
| S5 Rehearsal inside one repo | Planned |
| S6 Split, with history preserved | Planned |
Every step is one commit, and CI has to be green before the next one starts. What CI can't check is the editor UI itself, so each step also has a short manual checklist to run on Windows.

What I'd take from this
- Write the success test before the plan. "Runs with the engine checkout renamed" catches every hidden path dependency in one go.
- Check the code, not your memory. The serializer finding changed a decision from "warn" to "read-only".
- Decide from measurements. LFS sounded right until the numbers said otherwise.