
The Problem with My Old Workflow
For years, I've been using a GitFlow-inspired workflow with environment-specific branches that trigger deployments on pushes. This approach has some advantages - particularly being able to easily check out what's on any environment for local testing. The main branch is always synced with the production environment.
However, this workflow has created several headaches:
Managing multiple environment branches alongside a GitFlow integration branch leads to merge conflicts
Relying on fast-forward merges (making branches function more like tags) to keep things clean
GitHub's prevention of fast-forward merges in PRs breaks this workflow - deploying to production creates a new commit hash that must be merged back to the integration branch
The move to monorepos has magnified these problems. In our early monorepo setups, we triggered deploys on merges to deployment branches by using git inspection to determine what changed. This resulted in:
More severe merge conflicts
Unpredictable deployments
Inadvertently coupled deploys between applications
A Better Git Workflow for Monorepo CI/CD

After experiencing these pain points firsthand, I'm proposing a simpler, more robust workflow inspired by GitHub Flow:
Feature branches start from main and merge back to main when complete
Merges to main automatically deploy to dev environments
A single, shared GitHub Action creates releases that takes the specific app name as an input
Creating an app-specific release triggers production deployment only for that app
Manual deployments remain available via GitHub Actions for any environment when needed

Important to note: This workflow doesn't use a unified integration branch across all monorepo applications. Each app within the monorepo can maintain its own integration branch if its team prefers that approach. Despite sharing the same release action, each application maintains its own release namespace and deployment triggers, ensuring that apps can be deployed independently despite living in the same repository.
This approach eliminates environment branches entirely, simplifying our git history while providing clearer deployment triggers and better separation between environments.
What git workflow has worked best for your teams, especially when working with monorepos?
PS: Of course we need to hotfix things sometimes. Here's a flowchart for hotfixes:
