← Back to blog

GitOps is not about Git

Rico Twesten-Weber Principal DevOps Engineer
gitopsfluxcdplatform-engineeringdevops

Everyone says they’re doing GitOps. Most of them are lying.

Not intentionally. They genuinely believe that putting YAML in a repo and triggering a pipeline on push makes them GitOps practitioners. I believed the same thing for longer than I’d like to admit. But after migrating an entire homelab infrastructure from docker-compose to FluxCD-managed Kubernetes, I can tell you: the git part was the easiest, least important piece.

It’s not GitOps just because it’s in Git

Here’s the pattern I see everywhere: a team puts their Helm values in a Git repo. They wire up a CI/CD pipeline that runs helm upgrade on merge. They call it GitOps and move on.

What they’ve actually built is push-based deployment with version control. That’s CI/CD. It’s fine. But it’s not GitOps.

GitOps is about reconciliation, not triggers. The difference sounds academic until you’ve lived through a 2 AM incident where someone kubectl edit-ed a deployment in production and your “GitOps” pipeline had no idea. Your repo said one thing. Your cluster said another. Nobody knew which was true.

What reconciliation actually changes

When I set up FluxCD on my K3s cluster, the shift wasn’t in where I stored configs. It was in how I thought about drift.

FluxCD doesn’t wait for you to push. It continuously compares your desired state (the repo) with your actual state (the cluster) and corrects any difference. Every 60 seconds, my cluster reconciles. If someone manually changes a resource, FluxCD reverts it. If a node restarts with stale state, FluxCD fixes it.

This changes your mental model:

  • There is no “deploy” button. You merge, and the system converges. Deployments stop being a thing you do.
  • Drift still happens, but it gets automatically corrected. You stop worrying about it.
  • Your repo becomes the actual source of truth, not because someone wrote a policy doc, but because the system enforces it.

The homelab test

My Raspberry Pi cluster runs about a dozen services, from Paperless-ngx for document management to monitoring stacks and internal tools. Before FluxCD, my deployment process was: SSH into the node, docker-compose pull, docker-compose up -d, hope nothing breaks.

It worked until it didn’t. Configuration drift accumulated silently. The state on my NAS-mounted volumes diverged from what my compose files described. I had no single source of truth, just multiple sources of partial truth.

Switching to FluxCD wasn’t just a tool change. It forced me to declare everything: every namespace, every secret reference, every resource limit. The pain of making it all explicit paid off within weeks. When a Raspberry Pi’s SD card corrupted, I pointed FluxCD at a fresh node and had every service running within minutes. Not because I had good backups, but because my entire desired state was in Git.

Where teams go wrong

Three patterns I keep seeing:

If your pipeline does helm upgrade with --set flags that aren’t in your repo, you’ve broken the contract. Every parameter must be declared. No exceptions. The moment you have config that only exists in CI variables, your repo stops being the source of truth.

Running dev and prod from the same branch with environment variables is not GitOps. It’s a deployment accident waiting to happen. I use branch-based environments: main maps to production, feature branches get ephemeral environments. The branch is the environment.

And if you can’t see when FluxCD last reconciled, what it changed, and whether it succeeded, you’re flying blind. Reconciliation without observability is just automated chaos.

This matters more with AI-generated infra

AI-generated infrastructure code is coming fast. Claude Code can already generate valid Helm charts and Kustomize overlays. But generated code without reconciliation is dangerous. You’re trusting AI output to be correct on the first pass.

GitOps with reconciliation gives you a safety net. Generate the config, commit it, and let the reconciliation loop validate that what was generated actually converges to a working state. If it doesn’t, the loop catches it. The AI writes the YAML, but the reconciler is the one that has to live with it.

The one question that matters

If you’re doing GitOps, ask yourself: what happens when someone changes something in production without going through Git?

If the answer is “nothing, it just stays changed,” you’re doing CI/CD with extra steps. If the answer is “the system reverts it automatically within seconds,” that’s GitOps.

FluxCD, ArgoCD, whatever comes next. The specific tool doesn’t matter much. What matters is declared state, continuous reconciliation, and automatic correction. Everything else is just version control.

Rico Twesten-Weber

Principal DevOps Engineer. I build platforms that run themselves, and write about DevOps and AI.

Explore

Connect

© 2026 Rico Twesten-Weber Impressum Datenschutz