GitOps
4 min read
GitOps is an operational model where Git acts as the source of truth for the desired state of applications, infrastructure, or environments. Changes are proposed through commits or pull requests, then automation applies or reconciles those changes against the real system.
GitOps is closely related to Infrastructure as Code, but focuses more on the delivery and reconciliation workflow than on the configuration language itself.
Core Ideas
Git as Source of Truth
The repository contains the intended state of the system: manifests, configuration, deployment definitions, infrastructure code, policies, or environment declarations.
If the running system differs from Git, Git is treated as the authority unless there is an explicit emergency override.
Pull Requests as Change Control
Operational changes go through the same review flow as application code:
• A change is committed to a branch.
• A pull request previews the change.
• CI validates syntax, policy, tests, or plans.
• Reviewers approve the change.
• Merge makes the change official.
This creates an audit trail for infrastructure and deployment decisions.
Automated Reconciliation
A GitOps controller or automation pipeline compares the desired state in Git with the actual state in the environment.
When drift is detected, the system can:
• Apply the missing change.
• Revert unauthorized manual changes.
• Report the drift for review.
• Block unsafe changes through policy checks.
Declarative State
GitOps works best with declarative systems: the repository describes what should exist, not every manual step required to create it.
Common examples include:
• Kubernetes manifests
• Helm charts
• Kustomize overlays
GitOps vs CI/CD
CI/CD and GitOps often overlap, but they are not the same thing.
• Continuous Integration validates changes: tests, linting, builds, static analysis, policy checks.
• Continuous Delivery prepares changes for deployment: artifacts, release candidates, deployment plans.
• GitOps makes Git the source of truth for runtime state and uses automation to reconcile environments to that state.
A CI pipeline may build an image and update a deployment manifest. A GitOps controller may then notice the manifest changed and apply it to the cluster.
Push vs Pull Deployment
Push Based
A CI/CD pipeline directly applies changes to the target environment after a merge.
Examples:
• tofu apply in CI
• kubectl apply from a workflow
• SSH deployment scripts
This is simple, but the CI system needs credentials for the target environment.
Pull Based
An agent inside or near the target environment watches Git and pulls changes when the desired state changes.
Examples:
• Argo CD
• Flux
• A custom reconciliation service
This reduces the need for external deployment credentials and gives the environment an active role in maintaining its own state.
Benefits
• Auditability: every change is visible in Git history.
• Reviewability: operational changes can use pull requests and code review.
• Rollback: reverting a commit can restore a previous desired state.
• Consistency: environments are reproduced from versioned definitions.
• Drift detection: manual changes become visible because they differ from Git.
• Automation: deployments and infrastructure changes become repeatable.
Risks and Tradeoffs
• Bad commits can become bad deployments if validation is weak.
• Secrets need special handling; do not commit plaintext secrets. Use tools like sops, sealed secrets, external secret stores, or environment-specific secret injection.
• Emergency changes need a backflow path so manual fixes are later reflected in Git.
• Repository structure matters because unclear ownership or environment layout makes automation dangerous.
• Stateful systems need care because not every rollback is safe, especially for databases and migrations.
Common Repository Layout
A GitOps repository often separates reusable components from environment-specific state:
txt
repo/
├── apps/
│ └── my-service/
│ ├── base/
│ └── overlays/
│ ├── dev/
│ ├── staging/
│ └── prod/
├── infrastructure/
│ ├── networking/
│ ├── compute/
│ └── storage/
└── clusters/
├── homelab/
└── production/
The exact layout depends on the platform, but the important distinction is between reusable definitions and environment-specific desired state.
• Configuration drift
• Desired state
• Reconciliation loop
• Software delivery