Git, CI/CD & GitOpsLXXXV · GitOps RollbackArgoCD
Argo CD rollback and history — `argocd app rollback`, `argocd app history`, and the rollback UI
What you'll learn
- List the history of an Argo CD Application with `argocd app history`
- Roll back an Argo CD Application with `argocd app rollback` and a specific history ID
- Use the Argo CD UI rollback button and interpret its semantics
- Combine the Argo CD rollback with a Git revert to close the rollback loop
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
Argo CD’s rollback is the controller-side half of a GitOps
rollback. Every successful sync - whether automatic or manual,
whether triggered by a webhook or by a CLI invocation - is
recorded as an entry in the Application’s history. The history
is the rollback surface: argocd app history lists the entries;
argocd app rollback targets one. The UI exposes the same
operation as a Rollback button in the Application’s history
panel. The operations are additive: the Application object
records the rollback as a new sync, the cluster’s resources
converge to the targeted revision, and Git is unchanged.
The history model
An Argo CD Application tracks every sync the controller has performed. The history is a list of revisions, each with an identifier (a sequential ID), a source revision (the Git commit or Helm version that was applied), a deploy timestamp, and a status (Succeeded, Failed, or Running).
flowchart LR
A["Application api"] --> H1["ID 4 - rev 8a3f9d2 - Succeeded"]
A --> H2["ID 3 - rev 7c2e8b1 - Succeeded"]
A --> H3["ID 2 - rev 5b1a0c3 - Succeeded"]
A --> H4["ID 1 - rev 9d4e7f0 - Succeeded"]
Inspecting the history:
argocd app history $APP_NAME
Output is a table of revisions. Each row is one sync. The ID
column is what argocd app rollback targets. The revision
column is the Git commit (or the Helm version, or the OCI
digest, depending on the source type) that the sync applied.
The status column tells the operator which syncs are usable
as rollback targets: only Succeeded entries are reliable
rollback points.
The history window is configurable via the Application’s
.spec.revisionHistoryLimit field. The default is 10; the
field accepts any non-negative integer. A limit of 0 keeps
only the most recent sync, which means argocd app rollback
has nothing to revert to. The window must cover the rollback
need the team commits to.
Rolling back via the CLI
argocd app rollback takes an Application name and an
optional history ID. Without an ID, the command rolls back to
the previous successful sync. With an ID, the command rolls
back to that specific entry. The ID is a positional argument,
not a flag.
argocd app rollback $APP_NAME
argocd app rollback $APP_NAME $HISTORY_ID
The first form is the common case: “roll back to the previous
sync”. The second form is the precise case: “roll back to
revision 7c2e8b1, which is the deploy we want to be on”. The
ID is the number argocd app history prints in the ID column;
it is a sequential integer, not a Git SHA.
One precondition: the rollback refuses to run while automated sync is enabled - the controller would otherwise re-sync to the branch tip and undo the rollback on the next tick. Disable automated sync first, and re-enable it only after Git has been reconciled with a revert:
argocd app set $APP_NAME --sync-policy none
argocd app rollback $APP_NAME $HISTORY_ID
# ... git revert lands on the branch ...
argocd app set $APP_NAME --sync-policy automated
The operation writes a new sync to the controller that targets
the chosen revision. The controller re-applies the manifests
at that revision to the cluster, the cluster’s resources
converge, and the Application’s status moves to Synced once
the rollout completes. The history records the rollback as a
new entry with a new ID.
sequenceDiagram
participant Op as Operator
participant Argo as argocd CLI
participant C as Application controller
participant K as Cluster
Op->>Argo: app set $APP_NAME --sync-policy none
Op->>Argo: app rollback $APP_NAME 3
Argo->>C: sync to revision 7c2e8b1
C->>K: apply manifests at 7c2e8b1
K-->>C: resources converged
C-->>Argo: sync succeeded (new ID 5)
Argo-->>Op: rollback complete
The rollback is recorded as a sync. With automated sync
disabled for the duration, nothing re-syncs the Application
on its own - but the branch still points at the bad commit.
The next sync - triggered the moment automated sync is
re-enabled, or by argocd app sync - will compare the
cluster to the branch tip. If the branch tip is the same as
the rolled-back-to revision, the diff is empty and the
Application remains Synced. If the branch tip is the bad
commit, the diff is non-empty and the controller will
re-apply the bad manifests. The Argo CD rollback is therefore
incomplete without a Git revert (or a new commit that
supersedes the bad one); re-enable automated sync only after
the revert has landed.
Rolling back via the UI
The Argo CD UI exposes the same operation. The Application detail page has a History panel; each entry has a menu with a Rollback option. Selecting Rollback on an entry prompts for confirmation and runs the same operation the CLI runs.
flowchart TB
A["Application detail page"] --> B["History panel"]
B --> C["Entry ID 3 (rev 7c2e8b1)"]
C --> D["Rollback menu"]
D --> E["Confirm"]
E --> F["Sync to rev 7c2e8b1"]
The UI rollback is equivalent to argocd app rollback $APP_NAME $ID; it is the same controller call, with the same
precondition that automated sync is disabled. The advantage of
the UI is the visual identification of the target: the entry
shows the revision, the timestamp, the deployer (when SSO is
configured), and the source revision, which lets the operator
verify the target before confirming. The CLI rollback requires
the operator to know the ID and to trust that the ID maps to
the revision they want.
What the rollback does and does not do
The Argo CD rollback restores the cluster’s resources to the manifests at the chosen history entry. It does not touch Git. It does not touch the container registry, the Helm chart repository, or any external state. It does not roll back the cluster’s data; rows in a database that were written under the bad revision remain after the rollback (see LXXXV-02).
flowchart LR
A["argocd app rollback"] --> B["Cluster resources"]
A -.-> X["Git branch - untouched"]
A -.-> Y["Container registry - untouched"]
A -.-> Z["Database rows - untouched"]
The boundaries the rollback does not cross define its reach. A team that uses the rollback as the only recovery step has restored one artifact while leaving three others drifted.
Common failure modes
Three failure modes are specific to the Argo CD rollback:
- Rollback to a Failed entry. The history includes syncs
that ended in
Failed. Targeting a Failed entry re-applies manifests that did not converge the first time; the rollback will fail in the same way. The discipline is to verify the entry’s status before confirming the rollback. - Rollback past a destructive sync. A sync that included
a
Pruneoperation removed resources the previous sync had. Rolling back to a revision before the prune will re-create the pruned resources only if the manifests at that revision still declare them. If the manifests have moved on, the rollback is a partial reversion. - Stopping after the rollback, with the Git revert never
committed. The rollback restores the cluster; auto-sync
is off (as the rollback requires); the branch still points
at the bad commit. The Application’s status is
Syncedbut only because no one is asking the controller to reconcile. Re-enabling auto-sync, or runningargocd app sync, will re-apply the bad manifests. The revert must land before auto-sync is re-enabled.
The combination: rollback plus Git revert
The complete rollback runs the Argo CD rollback and the Git revert. The order is: disable automated sync (the rollback refuses to run while it is enabled), the cluster rollback first (the cluster is the live system; restore the live system first), the Git revert second (the branch is the record; update the record after), and re-enable automated sync once the revert has landed.
argocd app set $APP_NAME --sync-policy none
argocd app rollback $APP_NAME
git revert $BAD_COMMIT
git push origin main
argocd app set $APP_NAME --sync-policy automated
The Argo CD rollback restores the cluster within seconds. The Git revert restores the branch; the pull request that wraps the revert preserves the review and CI discipline. Re-enabling automated sync before the revert lands would re-apply the bad manifests; re-enabling after, the next sync confirms the diff is empty. The Application is Synced; the branch is at a known-good commit; the audit trail records both operations.
Production discipline
- Configure
.spec.revisionHistoryLimitto cover the rollback window the team commits to. A limit of 0 disables the rollback; a limit of 10 keeps the last ten syncs. - Verify the entry’s status before rolling back. A Failed entry is not a usable rollback target.
- Disable automated sync before the rollback; re-enable it after the revert merges. The rollback refuses to run while automated sync is enabled, and re-enabling it before the branch is reverted re-applies the bad manifests.
- Wrap the Git revert in a pull request. The revert goes through the same review and CI discipline as any other change.
- Confirm the next sync has an empty diff. The rollback is complete only when the branch and the cluster agree.
Cross-course references
- This course, Part LXXXV-01 (Git revert vs controller rollback) - the two halves of a rollback.
- This course, Part LXXVII (Argo CD architecture) - the Application CRD that records the history.
- This course, Part LIX-03 (Kubernetes rollback) - the Deployment-level rollback that the Argo CD rollback wraps.
Quiz
Knowledge check · 4 questions
Q1. An on-call engineer disables automated sync and runs `argocd app rollback api` during an incident. The cluster restores to the previous sync; the Application is Synced. The engineer re-enables automated sync but does not commit a Git revert. What happens when the next webhook fires and the controller reconciles?
Q2. Setting `.spec.revisionHistoryLimit: 0` on an Argo CD Application is a valid optimisation that reduces etcd storage by retaining only the most recent sync, with no operational consequences.
Q3. Name the two Argo CD CLI commands that cover the rollback cases, and state what each does.
Q4. Plan a rollback that combines the Argo CD CLI and a Git revert, and identify what to check in the Application's history before confirming the rollback.
At 11:14 the team deploys a new release to production via a pull request merged into main. The PR is commit 8a3f9d2. At 11:22 a 5xx spike is observed; the diff shows the new release introduced a bad liveness probe path. The on-call engineer opens the Argo CD UI for the Application, sees history entries ID 4 (rev 8a3f9d2, Succeeded, 11:14), ID 3 (rev 7c2e8b1, Succeeded, 10:02), and ID 2 (rev 5b1a0c3, Failed, 09:48). The engineer needs to roll back.
Passing score: 75%. Answers are checked in this browser.