git

Owns a git working tree on a remote host. Shells out to the system git binary over SSH — there is no libgit2 dependency. The provider takes no configuration block.

Kinds

git_repo

Clones a remote repository to a fixed path and keeps it pinned to a given ref. Producer kind: state captures the resolved commit_sha, which is what other steps (a docker_image rebuild, a ssh_exec post-deploy) can observe drift against.

resource "git_repo" "app" {
  host = host.primary.addr
  path = "/srv/app"
  url  = "https://github.com/example/app.git"
  ref  = "main"
}
attrrequiredtypedefaultdescription
hostyesstringSSH target.
pathyesstringAbsolute destination path on the remote host. The directory is created by git clone.
urlyesstringRemote URL. Passed verbatim to git clone. Authentication uses whatever's on the host (~/.git-credentials, deploy key in ~/.ssh, etc.) — stratum does not inject credentials.
refyesstringA branch name, a tag, or a full 40-character lowercase hex SHA. See Refs below for the dispatch rules.
depthnonumbernoneShallow-clone depth, passed to --depth. Only honored when ref is a branch or tag; full SHAs always clone full (--depth + bare SHA is fragile).

State shape

{
  "host": "root@192.0.2.10",
  "path": "/srv/app",
  "url": "https://github.com/example/app.git",
  "ref": "main",
  "depth": null,
  "commit_sha": "bfb77a6c1d808e04..."
}

commit_sha is the output of git rev-parse HEAD after the create / update. Stratum re-reads this on --refresh; a mismatch between the recorded SHA and what ref currently resolves to on the remote becomes drift, which update resolves with a fetch + reset.

Refs

The ref value dispatches at command-build time:

  • Branch or tag (anything not matching a full SHA shape) → git clone --branch <ref> [--depth N] <url> <path>. Updates run git fetch origin && git reset --hard origin/<ref>.
  • Full 40-character hex SHAgit clone <url> <path> && git -C <path> checkout <sha>. The --branch flag does not accept bare SHAs, so the clone-then-checkout shape is required. --depth is intentionally ignored for SHA refs. Updates run git fetch origin && git checkout <sha>.

A short SHA (bfb77a6) is treated as a branch name — git will reject it as a missing branch at clone time. Use the full 40-char form if you need SHA-pinned behavior.

Recreate vs in-place update

changeaction
url differsrm -rf <path> then re-clone. State preserves the new url + sha.
path differsrm -rf <old-path> then re-clone at the new path.
ref / depth onlygit fetch origin + git reset --hard origin/<ref> (or git checkout <sha>).

There is no git fetch --depth shrink / expand path — depth changes alone do not trigger any work today.

Drift detection

read runs a single-roundtrip probe:

if [ ! -d <path>/.git ]; then echo MISSING;
else printf '%s|' "$(git -C <path> rev-parse HEAD)";
     git -C <path> remote get-url origin;
fi
  • <path> or <path>/.git missing → Absent.
  • Probe output <sha>|<origin_url>Present { host, path, url, ref, depth, commit_sha }. The url in the observed value is the actual remote URL — if it differs from the desired url, the plan flags drift on url and the next apply will re-clone.
  • Anything else → Unknown with the unparsed output.

Apply trace

[git] CLONE git_repo `app` -> root@192.0.2.10:/srv/app (ref=main)
[git] UPDATE git_repo `app` (root@192.0.2.10:/srv/app) ref=main
[git] DELETE git_repo `app` (root@192.0.2.10:/srv/app)

Notes

  • Stratum does not manage SSH host keys for git remotes. If the remote is a private git server reached over SSH, the host running stratum's ssh (the remote host, not your laptop) needs to have already accepted the remote's host key.
  • Credentials live on the host. For GitHub HTTPS, the common pattern is to drop ~/.git-credentials via a system_secret_file sourcing a personal access token from secret { from_env = "GH_PAT" }.
  • git_repo does not run anything inside the cloned tree (no npm install, no docker build). Pair it with a docker_image (using the clone path as context) or an ssh_exec for post-clone work.