The Uncomfortable Truth
Here's a test: when your deployment fails in production, what happens to your main branch?
If the answer is "the broken code is already merged" — congratulations, you're doing CI/CD with a Git trigger. That's not GitOps. It's a pipeline that happens to watch a branch.
I've spent years building : declarative desired state, versioned in Git, automatically reconciled. The enforcement mechanism I'm describing is how you make those principles real rather than aspirational.
The Anti-Pattern Everyone Runs
The most common "GitOps" setup I see in enterprise teams looks like this:
- Developer opens PR
- CI runs tests
- Reviewer approves
- PR merges to
main
- Deployment triggers from
main
- ❌ Deployment fails
mainnow contains code that isn't in production
This is merge-then-deploy. It's standard CI/CD with extra steps. The moment you merge before confirming a successful deployment, you've broken the core GitOps contract: Git as the single source of truth for what's actually running.
The result? Drift. Stale state in main. A branch that lies about what's deployed. Every subsequent PR is now based on a broken foundation.
The Enforcement Pattern: Deploy Before Merge
The fix isn't philosophical — it's mechanical. using exactly this pattern — batch PRs into merge groups, test and deploy the group, merge only on success.
Environment Parity: The Force Multiplier
The MergeQueue pattern only works if you've solved the second GitOps requirement: environment parity.
Every environment — dev, staging, production — should deploy using the exact same scripts. The only difference is configuration parameters. If your prod deployment uses a different process than dev, you've introduced a variable that the merge queue can't validate.
Here's the mental model: environments aren't stages in a pipeline. They're instances of the same declaration with different inputs. Your Terraform modules, your Helm charts, your infrastructure definitions — same code, different .tfvars or values.yaml.
This is where I see the most breakage. Teams invest in merge queues but maintain hand-rolled production deployment scripts that diverge from their staging process. In my experience, the #1 thing that breaks production is environmental differences — not bad code, not missing tests, but a deployment process that works differently in prod than it did in staging. are entirely managed through code — every role assignment, every app registration, every permission scope. The MergeQueue pattern here means a misconfigured role never reaches production without a successful dry-run proving it resolves correctly.
AI Agents Make GitOps More Critical, Not Less
Here's where the conversation gets forward-looking. AI agents — matters more than ever when machines are the ones making commits.
This doesn't make GitOps obsolete. It makes it — and the GitOps substrate is how you get there.
Consider: if an AI agent can codify a process — user onboarding, access provisioning, network configuration — and you have a deterministic sync process validating that code, you can safely let agents manage entire operational domains. The . They don't hit APIs directly — they modify code, which flows through the same MergeQueue validation as human-authored changes. Policy violations surface as deployment failures. The agent's code either passes or it doesn't. No special paths, no elevated privileges, no drift.
The enforcement pattern:
- Agent proposes a change (PR)
- Merge queue validates deployment
- If it passes: merge. If not: reject.
- The agent is subject to the same rules as any engineer.
This is where the industry is heading. . But without GitOps as the substrate, autonomous agents become autonomous drift generators.
The Litmus Test
Before you call your workflow "GitOps," answer these three questions:
If a deployment fails, doesmainstill change? If yes — that's CI/CD.
Can you reconstruct every environment from Git alone? If no — you have drift.
Are agents and humans subject to the same merge rules? If no — you have a governance gap.
If all three pass, you're doing GitOps. If not, you're doing CI/CD with a Git trigger — and that's fine, but call it what it is.
The Bottom Line
GitOps isn't a tooling choice — it's an enforcement philosophy. The core contract is brutally simple: main equals production, always. The MergeQueue pattern is how you mechanically enforce that contract. Environment parity is how you make it trustworthy. And as AI agents become your primary infrastructure operators, that enforcement isn't just nice-to-have — it's the only thing standing between autonomous agents and uncontrolled drift.
Stop deploying after merge. Start merging after deployment. That's GitOps.
Resources
— CNCF
— Firefly
— Harness
— GitHub Docs
Microsoft Entra ID Platform Overview — Microsoft Learn
SOCIAL SHARE CARD GENERATOR