core.git
Clone and update a git repository on the host via the system git.
core.git invokes the system git as a subprocess (clone / pull --ff-only / rev-parse); the module contains no git client of its own. Idempotency goes by the presence of path/.git: cloned clones only when it is absent, pulled additionally pulls the remote and reports changed only when HEAD moves. clone/pull execute code from the repository (hooks, transport), so repo must point at a trusted source. The MVP deliberately does not cover changing the remote URL, submodules, lfs, or sparse-checkout.
Requirements
- Rootnot required
- Side
soul-side - Collection
soulstack.scm - Category
scm
exec_subprocessnetwork_outboundStates
core.git.cloned — A git repo lives at path (cloned when absent).
path/.git was absent and the repository was cloned.
path/.git already exists — the contents are not touched, no new pull is done.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
repo | string | required | Repository URL. |
path | string | required | Target clone directory. |
branch | string | optional | Branch (default main). |
depth | int | optional | Shallow clone depth (--depth). |
Example — Lay out the repository on the host (shallow clone)
- name: Clone deploy repo module: core.git.cloned params: repo: https://github.com/example/deploy.git path: /opt/deploy branch: main depth: 1Output
| Field | Type | Description |
|---|---|---|
path | string | |
cloned | true | |
head | string (current HEAD, sha, best-effort) |
core.git.pulled — A git repo lives at path, pulled up to the remote via git pull --ff-only.
path/.git is absent — a clone is performed. The repository is present — it changes only when HEAD has moved (comparing rev-parse HEAD before and after).
The repository is present and HEAD has not moved.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
repo | string | required | Repository URL. |
path | string | required | Target clone directory. |
branch | string | optional | Branch (default main). |
depth | int | optional | Shallow clone depth (--depth). |
Example — Keep the working copy in sync; register — to restart a service when HEAD moves
- name: Keep deploy repo up to date module: core.git.pulled register: deploy_repo params: repo: https://github.com/example/deploy.git path: /opt/deploy branch: mainOutput
| Field | Type | Description |
|---|---|---|
path | string | |
cloned | true | |
head | string (current HEAD, sha, best-effort) |
Notes
- Requires outbound network (network_outbound): clone/pull reach the remote repo.
- pull is fast-forward only (--ff-only): a diverged local history is not force-merged, the step fails — protection against silently losing local commits on the host.
- Authentication and transport (ssh-agent, credential helper, ~/.netrc) are on the system git's side; the module does not configure them.
- head in the output is best-effort: if rev-parse did not return a sha, the field is empty (this does not affect the main flow).
Security & defaults
- clone/pull execute code from the repository — the module's main risk: on checkout git runs the repo's hooks (.git/hooks/*: post-checkout, post-merge), and transport parameters can launch an arbitrary command. The module does not disable hooks and does not sandbox git.
- repo must point at a trusted source: cloning an untrusted repository = executing its author's code with the soul process's privileges; in practice, for system paths the agent runs as root, so the hooks run as root — the cost of trusting repo only grows.
- Argument-injection guard -- covers repo/path (a repo beginning with - will not be parsed by git as an option), but branch is substituted before -- and without validation — keep branch under the Destiny author's control, like repo.