Source control
One authoritative Git repository per app: DeepSpace source, GitHub source, and how to move between them.
On this page
Every app has exactly one authoritative Git repository. Which one is a server-enforced setting, not an inference from remote names — so before deciding anything from what git remote -v shows, ask the platform:
npx deepspace app source --json
The two providers#
| Source | Experience |
|---|---|
| DeepSpace | The packaged default. Commit-first: deploy publishes the attached clean branch automatically, and the space remote, clone/push/pull, workspaces, activity, releases, and rollback all work together. |
| GitHub | Manual ownership. You push with ordinary Git; an ordinary deploy ships the local working tree and performs no Git read, write, or verification. |
Under GitHub source, dirty and unpushed bytes are valid deploy inputs. The release records the configured repository and source revision but carries no DeepSpace commit id; rollback uses the retained deployment bundle. Do not add Git checks to this path — selecting GitHub means the developer owns synchronization, and the platform respects that.
Selecting or transferring authority#
npx deepspace app source github [--remote <name>]
npx deepspace app source deepspace [--remote <name>]
--remote names the local GitHub remote to verify or import when more than one exists (default origin).
An app with no source yet is making an initial claim, not a transfer. Claiming GitHub performs one read-only git ls-remote reachability check; an empty remote is valid. It does not require a clean worktree or a published local HEAD, because GitHub-source deploys intentionally ship dirty and unpushed local bytes.
Changing from one GitHub repository to another follows the same lightweight contract: one reachability check, then an atomic update guarded by sourceRevision. The exact branch, tag, and release checks below apply only when moving authority between DeepSpace and GitHub.
Always use the command. Never rewrite remotes or registry fields by hand to "move" an app — authority is a server-side fact, and hand edits only desynchronize your checkout from it.
The transfer is engineered to be safe:
Inventory
The command inventories branches, tags, and deploy lineage on the current provider.
Copy or request
It copies missing objects itself, or asks you to publish the exact refs it needs. GitHub → DeepSpace is the packaged path: verified refs are imported and the space remote and workspace surface are enabled. DeepSpace → GitHub stays manual because you own GitHub — create or select the intended remote, publish the requested refs, then rerun.
Verify and flip
It verifies exact object ids, then flips authority once. A failed copy or a stale source revision leaves the old provider authoritative — there is no half-transferred state.
Follow the command's one structured action when it returns one. Never bypass a refusal with --no-push — a one-release legacy escape for an unclaimed or DeepSpace-source app that skips source sync for that single deploy, shipping without commit lineage. It does not change authority and never bypasses GitHub source — moving between source modes is app source's job — so using it to dodge a transfer refusal ships code the authority flip has not verified.
What transfers, and what does not#
Transfers preserve Git history reachable through branches and tags. They do not move:
- app identity, data, secrets, collaborators, or URLs — those key to the app id and never depended on the repo host;
- Git LFS objects, submodule repositories, notes, replace refs, or host-specific metadata.
If the repo depends on LFS or submodules, resolve that before transferring — the flip will not carry them.
Who can change it#
Only the owner changes source authority. Collaborators and platform admins can inspect app source but cannot flip it.
Active DeepSpace workspaces must be landed or dropped before moving to GitHub — the workspace surface refuses under GitHub source, so anything still open would be stranded. See workspaces.
One authority, one remote#
Flipping to GitHub also removes the space git remote — the remote that points at the app's DeepSpace cloud repo. A stale one (left by an earlier pull on an unclaimed app, or inherited from a DeepSpace-era deepspace clone) still accepts git push space and answers with a bodiless HTTP 422, which is a confusing way to learn that DeepSpace no longer owns the repo. Flipping back to DeepSpace re-creates it.
app source --json reports which happened as spaceRemote:
| Value | Meaning |
|---|---|
removed | Moved to GitHub, and a space remote existed and was deleted |
absent | Moved to GitHub, and there was no space remote to delete |
present | Moved to (or stayed on) DeepSpace source; the space remote points at the cloud repo |
Human output prints the same fact as a line under the Source: line.
Working under GitHub source#
The rules of the road once GitHub is authoritative:
-
Push with ordinary Git. Branches, tags, PRs — all normal. DeepSpace Git writes and workspaces refuse with a source-authority error, by design.
-
Deploy ships the working tree. Including dirty or unpushed bytes. Commit discipline is yours.
-
Do not create or replace
originunprompted. Wiring a repo to GitHub is the developer's call. When asked, use ordinary Git:git remote add origin git@github.com:<org>/<repo>.git git push -u origin mainbash -
Publish a review branch by exact commit. To put precisely the checked-out state up for review:
git remote get-url origin git push -u origin HEAD:refs/heads/<review-branch>bash
The one refusal push, pull, and clone share#
All three DeepSpace source verbs refuse identically under GitHub source, with the code source_managed_by_github:
This app uses GitHub source (
owner/repo). Use normal Git/GitHub for source operations (clone, fetch, push);deepspace deployships the local working tree without changing Git.
--json carries repository and appId alongside the code, so an agent can name the repo it should have used without parsing the sentence. The refusal correctly ships no executable action: which Git command to run is the developer's call.
A review branch is not a second trunk#
A DeepSpace-source app may still keep a review branch on GitHub — that is fine. But GitHub is then not the deploy source, and you must not describe both remotes as authoritative or maintain two trunks as a product invariant. One repository is the truth; the other holds a copy for a purpose.
CI deploys#
For CI, inspect the current flags with npx deepspace auth login --help and npx deepspace deploy --help rather than copying stale snippets. Store credentials in the CI secret manager — never in argv, repository files, or workflow logs.
See also#
- Workspaces — the DeepSpace-source collaboration surface
- App identity — what stays put when the repo host changes
- Deployment — what a release records under each source
- Command reference:
app source