> ## Documentation Index
> Fetch the complete documentation index at: https://docs.diversion.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Submodules

> Mount another repo inside your repo, pinned to a commit

A submodule mounts one Diversion repo at a folder path inside another repo, pinned to a
specific commit. Use it to share an engine, a library, or an art pack across projects: each
project decides which version it uses, and upgrades are an explicit, reviewable change.

## Key terms

* **Mount path** — the folder in the parent repo where the other repo appears, for example `libs/engine`.
* **Pin** — the commit of the mounted repo that the parent points to. The pin is part of the parent's history, so everyone who syncs the parent gets the same version.
* **Child workspace** — the working copy of the mounted repo that Diversion creates inside the mount path. It is a real workspace: you can check out a branch, edit, and commit in it.

## Add a submodule

From anywhere inside the parent workspace:

```bash theme={null}
dv submodule add <repo> libs/engine                 # pin to the tip of the repo's default branch
dv submodule add <repo> libs/engine --ref <commit>  # pin a specific commit
```

`<repo>` is the mounted repo's name or ID. The files appear at `libs/engine`, and the pin is
committed in the parent, so teammates get the submodule when they sync.

Diversion refuses to mount over a folder that already has files, on a symlink, or at a path
that differs from an existing mount only by letter case (such paths open the same folder on
Windows and macOS).

## See what state your submodules are in

```bash theme={null}
dv submodule status
```

```
PATH         REPO    PINNED COMMIT   STATE         LOCAL CHANGES
libs/engine  engine  dv.commit.42    synced        0
libs/tools   tools   dv.commit.7     pin_mismatch  2
```

* `synced` — the local mount is at the pinned commit.
* `missing` — the pointer exists but the files were not created locally yet (for example, right after cloning the parent). Run `dv submodule update`.
* `pin_mismatch` — the local mount is at a different commit than the pin, usually after committing inside the mount.

`LOCAL CHANGES` counts uncommitted changes inside the child workspace. It shows `paused`
when the child workspace's sync is paused, because a paused workspace cannot report its
changes.

The parent's regular `dv status` also warns when any submodule needs attention:

```
Submodules with pending work:
	 libs/engine (engine): not on its pinned commit, 1 uncommitted change
```

## Get or repair the files

```bash theme={null}
dv submodule update
```

`update` makes the local mounts match the pins: it clones missing mounts, moves drifted
mounts back to the pinned commit, and re-creates a mount folder that was deleted. It never
touches a mount that has uncommitted work or is on a branch — your work is safe.

## Work inside a submodule and move the pin

The mount is a working clone. To change the mounted repo and point the parent at the result:

```bash theme={null}
cd libs/engine
dv checkout main            # the child starts detached; a commit needs a branch
# edit files
dv commit -a -m "my change"
cd ../..
dv submodule repin libs/engine
```

`repin` moves the pin of an existing submodule. Without `--ref` it pins the child
workspace's current commit — what you just built and tested. To pin a different commit:

```bash theme={null}
dv submodule repin libs/engine --ref <commit>
```

Moving a pin never overwrites work: if the mount has uncommitted changes, the repin is
refused until you commit or undo them.

## Remove a submodule

```bash theme={null}
dv submodule rm libs/engine
```

Removes the pointer and the local files. Like `update`, it refuses while the mount holds
uncommitted work.

## Good to know

* Commands run inside the mount apply to the mounted repo, not the parent. `dv status` in `libs/engine` shows the child's changes.
* Edits inside the mount never show up as parent changes; the parent repo stays clean.
* The child workspace is named `<folder> submodule @ <your machine>` in the workspace list, so it is easy to tell apart from a regular clone.
* In the web app, the parent's file tree shows a mount with a tree icon and a tooltip naming the mounted repo and its pinned commit.
* The pin is part of the parent's history. Branching, merging, and going back in time in the parent carry the pin with them like any other change.
