Branching and Merging Strategy
Categories:
Problem
In a GitOps setup with Ansible, managing changes across multiple environments like development, staging, and production requires a structured approach to avoid errors, ensure testing, and maintain security. Without clear branching policies, teams risk deploying untested code, conflicting changes, or unauthorized modifications to critical branches.
Context
GitOps practices involve using Git as the single source of truth for infrastructure and application configurations. In Ansible-based projects, this means storing inventory, playbooks, and variables in a Git repository, in a so-called Ansible inventory project. Branches can represent different environments, allowing changes to be promoted via merge requests (MRs). Protected branches in tools like GitLab or GitHub enforce reviews, approvals, and CI/CD pipelines before merges, ensuring changes are vetted and tested automatically.
Solution
Implement a branching strategy that aligns with GitOps principles, using environment-specific environment branches and merge requests for promotions. Enforce policies with protected branches to maintain control and auditability.
Follow these guidelines:
Define Core Branches: Create permanent branches for each environment. These are so-called environment branches. It is important that they match an environment consisting of hosts that are part of the same Ansible environment group.
master: Serves as the stable, long-term branch that reflects the latest production state after successful promotions.development: For ongoing development and feature work.staging: For testing changes before production.production: Represents the live production environment; only merge from staging after approvals.
Branching Policies:
- Feature branches: Create short-lived branches off
developmentfor new features or bug fixes (e.g.,feature/add-new-playbook). - Hotfix branches: For urgent production fixes, branch directly from
production(e.g.,hotfix/issue-12345). - Avoid direct commits to environment branches; always use MRs for changes.
- Feature branches: Create short-lived branches off
Merging Workflow:
- Develop and test in
development. - Merge from
developmenttostagingvia MR for integration testing. - Merge from
stagingtoproductionvia MR after approvals and successful CI/CD runs. - Finally, merge
productionback tomasterto keep it updated. - For hotfixes: Apply to
productionfirst via MR, then backport to other branches.
- Develop and test in
Protected Branches:
- Configure branch protection for all
environment branches and for
masterin your Git platform (e.g., GitLab):- Require MR approvals (e.g., at least 2 reviewers).
- Enforce passing CI/CD pipelines before merging.
- Restrict who can push or merge (e.g., only admins for
production). - Prevent force pushes and branch deletion.
- Configure branch protection for all
environment branches and for
Automation Integration:
Benefits
- Consistency and Safety: Reduces deployment risks by enforcing reviews and automated testing.
- Traceability: MRs provide an audit trail of changes and approvals.
- Scalability: Supports team collaboration without overwriting work.
- Rollback Ease: Environment branches allow quick reverts if issues arise.
Alternatives
While Git Flow or GitHub Flow are common, they may not align perfectly with GitOps’ environment-based promotions. A simpler trunk-based development could work for smaller teams but lacks the staged promotion needed for regulated environments; the described strategy is preferred for Ansible GitOps setups requiring clear separation.
Examples and Implementation
In a typical Ansible GitOps project, structure your repository with branches representing environments. Use merge requests to promote changes, triggering CI/CD pipelines that run Ansible playbooks for deployment.
Here’s an example Git workflow visualized with Mermaid:
gitGraph
commit id: "Initial commit"
branch development
checkout development
branch staging
checkout staging
branch production
checkout production
checkout development
commit
commit
commit id: " " tag: "1.0.0"
checkout staging
merge development tag: "1.0.0"
checkout production
merge staging tag: "1.0.0"
commit id: "Production release 1.0.0"
checkout main
merge production tag: "1.0.0"
checkout production
branch hotfix-12345-fix-something
commit id: "Hotfix applied" tag: "1.0.1-hotfix-issue-12345"
checkout main
merge hotfix-12345-fix-something tag: "1.0.1-hotfix-issue-12345"
checkout development
merge hotfix-12345-fix-something tag: "1.0.1-hotfix-issue-12345"
checkout staging
merge hotfix-12345-fix-something tag: "1.0.1-hotfix-issue-12345"This diagram illustrates:
- Initial setup of branches.
- Development work merged to staging, then production.
- A hotfix applied to production and backported to other branches.
- Final merge to
masterfor a stable record.
Additional Information
- Ansible Inventory Project: A structured collection of files used for managing hosts and configurations. It typically includes inventory files, playbooks, host configurations, group variables, and Ansible vault files.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.