Skip to main content

Git Configuration

The git section in atmos.yaml makes Git a foundational Atmos capability — a peer to Toolchain, Auth, and Hooks. Define managed repositories once under git.repositories, then clone, pull, diff, commit, and push them by logical name from the atmos git commands, kind: git lifecycle hooks, and native CI workflows — with consistent authentication, safety rules, and workdir handling. It is the foundation for GitOps workflows with Atmos: commit generated artifacts to a source-of-truth repository that Argo CD, Flux, or your CI consumes.

You will learn

  • Define managed repositories by logical name under git.repositories
  • Authenticate through Atmos Auth identities and integrations — credentials are never embedded in URIs
  • Clone is always reconcile: idempotent and safe under restored CI caches
  • Automatic workdirs under the Atmos XDG cache root are captured by the native CI cache for free
  • Configure local Git hooks (pre-commit, commit-msg, ...) that delegate to Atmos workflows

Basic Configuration​

atmos.yaml
git:
repositories:
flux-deploy:
uri: https://github.com/acme/flux-deploy.git
auth:
identity: platform-admin
commit:
signing: auto

generated-terraform:
uri: https://github.com/acme/generated-terraform.git

hooks:
pre-commit:
command: atmos workflow pre-commit
commit-msg:
command: atmos workflow commit-msg -- "$1"

The keys under git.repositories (flux-deploy, generated-terraform) are arbitrary, user-defined logical names — not reserved values. Components, hooks, and commands refer to repositories by these names. Repository configuration follows standard Atmos deep-merge, so repositories can be defined in imported configuration and overridden per environment.

Repository Fields​

All fields a repository supports:

atmos.yaml
git:
repositories:
flux-deploy:
provider: cli # optional; cli is the default
uri: https://github.com/acme/flux-deploy.git
branch: main
remote: origin
workdir: .workdir/git/flux-deploy # optional; default is automatic XDG
clone:
depth: 1 # shallow clone depth; 0 = full history (default)
filter: blob:none # optional partial-clone filter
single_branch: true
submodules: false # default false
auth:
identity: platform-admin
commit:
signing: auto # auto | always | never
author:
name: atmos[bot]
email: atmos-bot@acme.com
push:
retries: 3
init:
from: https://github.com/acme/flux-template.git # optional seed source for `atmos git init`
keep_history: false # preserve source history as `upstream` (requires `from`)
provider

Execution backend for Git operations. Default and currently the only value: cli (shells out to the Git CLI). cli is host-agnostic — it works with GitHub, GitLab, Bitbucket, and bare repositories.

uri

Remote repository URI. Credentials must never be embedded in uri — authentication flows through the process environment and Atmos Auth, never through URL rewriting with tokens.

branch

Branch to check out. Empty means the current branch for existing workdirs, and Git's default-branch behavior for fresh clones.

remote

Remote name. Default: origin.

workdir

Explicit workdir location, overriding the automatic XDG location (see Automatic Workdirs).

clone.depth

Shallow clone depth. 0 (default) means full history. Also settable per invocation with --depth (flag wins: CLI > ENV > config > defaults).

clone.filter

Partial-clone filter spec (for example, blob:none). Also settable per invocation with --filter.

clone.single_branch

Limit the clone to the configured branch. Also settable per invocation with --single-branch.

clone.submodules

Initialize submodules after clone. Default: false.

auth.identity

The Atmos Auth identity used for Git operations against this repository. See Authentication Resolution.

commit.signing

Commit signing mode: auto (default — pass no signing flag; Git config decides), always (pass -S), or never (pass --no-gpg-sign). Overridable per invocation with --sign / --no-sign.

commit.author.name / commit.author.email

Commit author identity, passed per invocation (-c user.name=... -c user.email=...) without mutating repository or global Git config. Required in CI, where runners typically have no user.name/user.email configured. Locally, when Git already resolves an author, Atmos passes nothing — your own Git config wins.

push.retries

Bounded retry count for rejected non-fast-forward pushes (pull --rebase, then re-push). Default: 3. 0 disables retries.

init.from

Default seed source for atmos git init — the repository URI whose content bootstraps this repository (a template, or a repository being migrated). When omitted, init creates an empty repository. Overridable per invocation with --from (flag wins: CLI > ENV > config > defaults).

init.keep_history

When seeding via init.from, preserve the source's full history and keep it reachable as the upstream remote so future updates can be pulled. Default: false (fresh history — a single initial commit). Only valid together with init.from. Overridable per invocation with --keep-history.

Defaults​

When fields are omitted:

FieldDefault
providercli
remoteorigin
branchCurrent branch for existing repos; Git default-branch behavior for clone
workdirAutomatic XDG cache location (see below)
commit.signingauto
commit.authorIdentity-derived when available; otherwise an atmos[bot]-style default
push.retries3
clone.depth0 (full history)
clone.submodulesfalse

Automatic Workdirs​

When workdir is omitted, Atmos resolves a deterministic location under the Atmos XDG cache root:

$XDG_CACHE_HOME/atmos/git/repositories/<name>

with the standard XDG fallbacks and ATMOS_XDG_* overrides. Because the native CI cache archives the XDG cache root, managed clones are captured and restored across CI runs for free. An explicit workdir overrides the automatic location.

Clone Destinations​

The two-repo split (managed repositories vs. the current repository) extends to clone destinations:

Clone formDestination
Named managed repository (atmos git clone flux-deploy)Automatic XDG workdir (cache-captured)
Single configured repository outside CI (atmos git clone with exactly one repository)Automatic XDG workdir (cache-captured)
No-arg current-repo checkout replacement in CI (atmos git clone with ci.enabled: true and detected CI metadata)The working directory (e.g., GITHUB_WORKSPACE), exactly like actions/checkout — never an XDG workdir; subsequent Atmos commands expect the repo at CWD
Ad hoc URI (atmos git clone https://...)<cwd>/<repo-name>, like plain git clone

--workdir=<path> overrides the destination in all forms.

Clone Is Reconcile​

Workdirs persist across runs — and the native CI cache restores them, possibly stale. Clone semantics are therefore defined as reconcile, not "fail if exists":

  1. Workdir absent → clone.
  2. Workdir present and clean → fetch, check out the configured branch, fast-forward to the remote ref.
  3. Workdir present and dirty from a crashed or interrupted run → defined recovery: discard uncommitted changes inside managed paths only and re-reconcile; fail with a hint when unmanaged dirty files are present.

Reconcile makes clone behavior independent of cache freshness: a cache hit means fetching the delta instead of a full clone; a cache miss means a fresh clone; correctness is identical either way.

Authentication Resolution​

auth.identity is the only named auth reference on a repository. Integrations are never referenced by name from git config — they attach to identities via their via link, and naming an identity on a repository brings its integrations along automatically. For example, a github/sts integration linked to platform-admin materializes GIT_CONFIG_* credentials for every Git subprocess targeting the repository, with zero Git-specific auth wiring:

atmos.yaml
auth:
identities:
platform-admin:
kind: github/user # illustrative
integrations:
deploy-sts:
kind: github/sts
via:
identity: platform-admin

git:
repositories:
flux-deploy:
uri: https://github.com/acme/flux-deploy.git
auth:
identity: platform-admin # pulls in deploy-sts via the identity link

Per-operation resolution order:

  1. --identity=<name> flag (the global persistent flag).
  2. git.repositories.<name>.auth.identity.
  3. Ambient credential broker: when no identity is configured, the lazy ambient broker runs before the first Git subprocess. This is the zero-config CI path — atmos git clone of a private GitHub repository works with no auth block at all when an auto-provision github/sts integration (or an ambient GITHUB_TOKEN) is available.
  4. Process environment passthrough: your own Git credentials (credential helpers, SSH agent) always work, since the Git CLI provider inherits the process environment.

See Authentication for identities and integrations.

Local Git Hooks​

The git.hooks section maps Git hook names to commands or ordered step lists, invoked via thin .git/hooks/* shims installed by atmos git hooks install:

atmos.yaml
git:
hooks:
pre-commit:
command: atmos workflow pre-commit
commit-msg:
command: atmos workflow commit-msg -- "$1"
git.hooks.<hook-name>

A Git hook name: pre-commit, commit-msg, pre-push, and so on.

git.hooks.<hook-name>.steps
An ordered list of registered Atmos steps. Use this instead of command to run inline scripts and other step types inside Atmos. An empty list is not a hook implementation.
git.hooks.<hook-name>.command

The command to execute when the hook fires. Hook commands should usually invoke an Atmos workflow or custom command, which preserves existing toolchain, environment, and identity behavior. Hook arguments and stdin are forwarded.

Local Git hooks are triggered by Git itself in the current repository. They are separate from Atmos lifecycle events — for event-bound Git publishing (e.g., commit after terraform apply), use the kind: git hook.

List Output​

The git.list section configures atmos git list output, following the established <section>.list.columns pattern:

atmos.yaml
git:
list:
format: table
columns:
- name: Name
value: "{{ .name }}"
- name: URI
value: "{{ .uri }}"
git.list.format

Default output format: table, json, yaml, csv, or tsv.

git.list.columns

Column definitions (name + value template). Available row fields: name, uri, provider, branch, workdir, and status (populated only with --check-status). Custom columns also feed dynamic tab completion for --columns.

Native CI Lifecycle​

With ci.enabled: true, Git composes with the native CI cache and Atmos Auth into a complete job lifecycle:

  1. Job starts. CI cache auto-restore brings back the Atmos XDG cache root — toolchain binaries and managed-repo Git workdirs from the previous run.
  2. atmos git clone (no-arg) puts the current repository in the workspace, replacing actions/checkout. Fetch-depth guidance applies when atmos describe affected will run against this clone.
  3. atmos git clone --all reconciles the restored XDG workdirs: a cache hit fetches the delta instead of performing a full clone; a cache miss performs a fresh clone.
  4. First Git subprocess triggers the ambient broker — GitHub STS materializes GIT_CONFIG_* credentials for Git subprocesses.
  5. Operations run: render, publish, commit, push (with retry).
  6. Command end: the CI cache pending-save archives the XDG root for the next run.

A minimal GitHub Actions job replacing actions/checkout + actions/cache glue:

.github/workflows/publish.yaml
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: cloudposse/github-action-setup-atmos@v2
- run: atmos git clone # checkout replacement (workspace)
- run: atmos git clone --all # reconcile all deployment repos (XDG, cache-warm)
- run: atmos kubernetes deploy argocd -s prod # render + publish via hooks

Cache restore/save and STS credential minting happen inside the Atmos commands — no actions/checkout, actions/cache, or token-wiring steps.

Cache churn

Git workdirs change on every publish, so they churn cache archives. This is safe — workdirs are regenerable and always reconciled. To keep archives lean, scope ci.cache.paths to exclude git/repositories/, trading cache hits for full clones. atmos git list --check-status shows what is currently materialized under the cache root.

Inline script steps​

Keep small checks inside the hook configuration. Starlark scripts run in-process and can call the step library:

git:
hooks:
pre-commit:
steps:
- name: check-instruction-size
type: script
interpreter: starlark
script: |
for path in fs.glob("CLAUDE.md"):
if fs.stat(path).size > 40000:
errors.build("CLAUDE.md exceeds 40,000 bytes").fail()
- name: report
type: script
interpreter: starlark
script: ui.success("Repository checks passed")

Choose exactly one of command or a non-empty steps list. Install the shim with atmos git hooks install, then run it directly with atmos git hooks run pre-commit. Existing command hooks keep their argument and stdin forwarding behavior.

Steps run in order and stop at the first failure. They share named outputs and step environment changes. Each step supports its handler's timeout and retry behavior; embedded scripts also have access to steps.parallel. Git hook arguments are available as ctx.args in embedded scripts, for example the commit-message path supplied to commit-msg. Git's pre-commit hook supplies no filenames: query the Git index explicitly when a check needs tracked or staged paths.

Relative paths resolve from the invocation directory, unless a step sets working_directory. Git normally invokes client-side hooks from the working-tree root. These checks read working-tree files; Atmos does not stash unstaged changes or limit checks to the staged contents automatically.

Hook step lists use synchronous execution. Workflow scheduling fields (needs, when, continue, identity, background execution, and freshness policies) are rejected. Use an explicit container step for container operations. Background-job handlers require a workflow context. Use a workflow when a hook needs that scheduling.

See two inline repository checks for tracked symlink validation and separate size limits for CLAUDE.md and agent files.