atmos git push
Push commits from a repository configured under git.repositories, or from any local path, to its remote. Atmos never force-pushes. When a push is rejected because the remote moved (another job or human pushed first), Atmos automatically retries: pull --rebase, then re-push, with four total attempts by default. Custom push.retry policies apply only when pushing by a configured repository name. A local path uses legacy defaults even when it points to a configured repository; use the repository name to apply its policy.
Usage
atmos git push <name-or-path> [flags] [-- <native git args>]
With a configured repository:
git:
repositories:
flux-deploy:
uri: https://github.com/acme/flux-deploy.git
push:
retry:
max_attempts: 12
backoff_strategy: exponential
initial_delay: 1s
max_delay: 30s
multiplier: 2
random_jitter: 0.5
max_elapsed_time: 10m
atmos git push flux-deploy
Examples
# Push a managed repository to its configured remote/branch
atmos git push flux-deploy
# Push a repository at a local path
atmos git push ./deployments
# Push a specific branch to a specific remote
atmos git push flux-deploy --remote=origin --branch=main
# Report what would be pushed without pushing
atmos git push flux-deploy --dry-run
# Pass native arguments to the underlying git push invocation
atmos git push flux-deploy -- --follow-tags
Push Contention
For workload sizing, platform limits, and publishing from multiple source repositories, see Concurrent Git Publishing.
A rejected non-fast-forward push is the most common failure mode in GitOps publishing — multiple components, CI jobs, or humans pushing to the same deployment branch. Atmos handles it instead of surfacing a raw Git error:
- On rejection, including a concurrent remote ref update (
cannot lock ref ... is at ... but expected ...), runpull --rebase, then re-push. - Wait with exponential backoff and random jitter, then retry according to
push.retry(four total attempts by default; configurable per repository). - After exhaustion, fail with a clear error. Size the retry budget for bursts from independent publishers.
Configure backoff and jitter using the shared retry policy under git.repositories.<name>.push:
push:
retry:
max_attempts: 4 # initial attempt plus up to three retries
backoff_strategy: exponential
initial_delay: 250ms
max_delay: 5s
multiplier: 2
random_jitter: 0.5
max_elapsed_time: 30s
max_attempts includes the initial attempt. max_elapsed_time bounds the entire operation, including running Git commands. The delay cap applies before jitter. An explicit policy uses shared retry semantics. Omitted fields are not inherited from the defaults: max_attempts and max_elapsed_time are unlimited, and initial_delay is 0s. Set all three fields for a bounded policy; retry: {} or max_attempts: 1 makes one attempt. Legacy push.retries remains supported when push.retry is absent. Legacy and path-based pushes use a 30-second retry-scheduling budget without imposing a deadline on running Git commands; the caller’s context still applies. Optional conditions narrow the rejected-push messages eligible for retry; they never enable retries for authentication failures or unrelated errors.
Remote Rate Limits
Push and its recovery fetch recognize HTTP 429, HTTP 403 with rate-limit response metadata, and explicit rate-limit diagnostics. Ordinary authentication failures still stop immediately. A throttled push waits and retries without rebasing; a throttled recovery fetch retries before the next push.
Atmos honors Retry-After (seconds or an HTTP date) and X-RateLimit-Reset when X-RateLimit-Remaining is zero. Without a usable hint, it waits at least one minute. Repeated throttling increases that minimum exponentially. Configured random_jitter adds only positive jitter to this cooldown, so publishers spread out without retrying before the server permits it.
Server cooldowns take precedence over max_delay; max_attempts and max_elapsed_time remain hard limits. If the cooldown cannot fit in the remaining elapsed-time budget, Atmos returns a rate-limit error immediately instead of retrying early. The default 30-second budget cannot accommodate a one-minute cooldown; the first example in Usage, with max_elapsed_time: 10m, allows a longer window. conditions restrict rejected-ref recovery, not recognized rate-limit recovery.
Each invocation reacts independently. There is no shared lock, concurrency group, or global rate counter across source repositories. This reduces retry pressure after throttling but does not guarantee an aggregate write rate or prevent the initial burst. Git transport limits are distinct from REST/GraphQL API budgets; Atmos does not poll GitHub APIs to predict them. See GitHub's rate-limit recovery guidance.
Only status and cooldown metadata are retained from HTTP tracing; trace headers and payloads are excluded from diagnostics. SSH has no HTTP headers, so explicit rate-limit messages use the fallback cooldown.
Arguments
name-or-path(required)A repository name configured under
git.repositories, or a filesystem path to an existing Git working tree. URIs are not accepted — push operates on a local workdir.
Flags
--branch/-b(optional)Branch to push. Defaults to the repository's configured branch, or the current branch. Environment variable:
ATMOS_GIT_BRANCH--remote(optional)Remote name. Default:
origin. Environment variable:ATMOS_GIT_REMOTE--dry-run/-n(optional)Report what would be pushed without pushing. Environment variable:
ATMOS_GIT_DRY_RUN--identity(optional)Atmos Auth identity to use for this operation (global flag). Overrides the repository's
auth.identity. Environment variable:ATMOS_IDENTITY
Native Git Arguments
Arguments after -- are passed verbatim to each underlying git push invocation (not to the pull --rebase recovery between retries).
atmos git push flux-deploy -- --follow-tags
Related
atmos git commit— create the commit to pushkind: githooks — commit and push automatically on lifecycle events- Git Configuration —
push.retryand authentication resolution