I've been struggling with my team's DevOps and GitOps workflow for a couple of years now, and it's really overwhelming. The current setup has branches assigned to specific deployment environments, which makes things more complicated than they need to be. Here's how it works: my team pushes code to their feature branches and then requests me to merge their changes into the develop and staging branches, which are linked to different environments. After I merge the code, I wait for the CI/CD pipeline to finish before confirming the deployment via chat. The promotion process to production involves moving changes from the feature branches to a release branch and then to production.
The branches are structured like this:
1. The develop branch is for development, not local machines.
2. Staging is aligned with develop but has a different commit hash.
3. Release branches are used for UAT.
4. The master branch is for production.
Unfortunately, not all feature branches that get merged into develop and staging end up in master—they often go stale. I'm looking for ways to make this workflow more streamlined and as self-service as possible, but my team seems hesitant to adopt new processes. They primarily just want to commit and push without thinking too much about GitOps. My personal preference would be to simplify this down to just using the master branch, splitting environments there, and promoting based on the same git commit hash. I want to shift to pushing to master, deploying to the dev environment, and then requesting promotions to staging and production. Any tips on how to approach this?
3 Answers
In my setup, the infrastructure repo is strictly governed by the main branch. For clusters and services, we have a well-organized folder structure. When a feature branch is created, a job generates the environment in the infra repo, and developers take care of their own environments without me having to worry about the details. Once their work is done, the folders get cleared automatically, which keeps everything tidy.
We switched to a trunk-based workflow using a single main branch. My feature branches are only temporary and merge directly into the main branch with pull requests. This allows for frequent updates, and we have policies in place to ensure quality. Each night, our system automatically promotes changes from main to staging as long as there’s a non-breaking build, which can also be manually triggered when needed. Production releases happen only when a tag is created, so no tag means no deployment to production.
I keep things simple with just one main branch where all the changes happen. We use directories and merge requests for updates. I have a declarative configuration that is straightforward—nothing too complicated, really. That way, I don’t have to deal with a lot of extra processes.

How do you keep a clear separation between production and other environments from a security standpoint?