Repo-splitting
Tools for splitting an app (or the shared backend) out into its own repository. Available since @devorajs/cli@0.2.0.
devora split/sync/status let you pull an app or packages/backend out of the main repo into its own, independently-clonable repo, while still building/deploying it from here. This is real Git underneath — a real submodule and a handful of fetch/merge/push commands, not a new devora-invented sync protocol. If you already know how Git submodules work, you already know most of what this does.
Two use cases
A solo dev wanting cleaner repo boundaries — maybe packages/backend has grown into something worth versioning and tagging on its own, independent of every app's release cadence. A real team where different people own different pieces independently — one person on packages/backend, one on apps/admin, one on the marketing site — each cloning and working in just their own piece, integrating back via explicit sync rather than one shared working tree.
devora split <app-name|backend> --repo=<git-url>
You create the empty remote repo yourself first — this tool doesn't create accounts or repos on your behalf, the same way devora deploy requires vercel link/netlify link to already exist. What actually happens, in order:
- The directory's current content is pushed to
--repoas that repo's real initial commit. - The directory is removed from the main repo's own tracked files.
- It's re-added at the same path via a real
git submodule add.
Nothing is committed in the main repo automatically — review with git status/git diff --cached and commit it yourself, the same pattern devora new/remove already use. After this, a fresh clone of the main project needs a real git submodule update --init to populate it — standard Git behavior this doesn't automate away.
devora sync <name> [--from-main | --to-main]
A thin wrapper around fetch/merge/push against a split-off piece's own remote, one direction at a time. --from-main merges the remote's latest into your local checkout and stages the updated reference in the main repo; --to-main pushes commits you made directly inside that checkout up to its own remote. Both show a real commit list and ask for confirmation before doing anything.
A genuine same-line conflict between two contributors is a real Git conflict — surfaced exactly the way a plain git merge would (real conflict markers, git status showing "Unmerged paths"), naming the conflicting file(s). This tool does not attempt to auto-resolve it: fix it inside the submodule's own checkout the normal way, then re-sync if the resolution needs to go back to the remote.
devora status --all
One view across every split-off app/backend: up to date, local commits not yet pushed, remote commits not yet pulled, diverged, or a gitlink change not yet committed in the main repo.
What this doesn't do
- Auto-resolve conflicts — a real conflict is real work; this tool's job is surfacing it clearly.
- Create remote repos or manage credentials — you create the empty repo and have push access before running
split. - Replace
git submodule update --initon a fresh clone — standard Git behavior, unchanged.
Ownership rules that matter more once repos are split
Two conventions from Backend matter most exactly when different people own different split-off pieces: shared backend logic still goes in packages/backend (an app's API route file just imports from @devorajs/backend normally — splitting only changes how that package's source is tracked, not where routes are declared), and every use of a middleware ecosystem adapter is still registered in one place, packages/backend/middleware.ts — now that repo's own owner's file to review, regardless of which app's contributor wanted to use it.