# atmos git push

Push commits from a repository configured under [`git.repositories`](/cli/configuration/git), 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

```shell
atmos git push <name-or-path> [flags] [-- <native git args>]
```

With a configured repository:

```yaml
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
```

```shell
atmos git push flux-deploy
```

## Examples

```shell
# 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](/best-practices/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:

1. On rejection, including a concurrent remote ref update (`cannot lock ref ... is at ... but expected ...`), run `pull --rebase`, then re-push.
2. Wait with exponential backoff and random jitter, then retry according to `push.retry` (four total attempts by default; configurable per repository).
3. 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](/steps/retry) under `git.repositories.<name>.push`:

```yaml
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](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api#exceeding-the-rate-limit).

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).

```shell
atmos git push flux-deploy -- --follow-tags
```

## Related

- [`atmos git commit`](/cli/commands/git/commit) — create the commit to push
- [`kind: git` hooks](/stacks/hooks#kind-git) — commit and push automatically on lifecycle events
- [Git Configuration](/cli/configuration/git) — `push.retry` and authentication resolution
