A Git repository can become difficult to manage when every developer creates, merges and releases branches differently. A clear git branching strategy defines how code moves from development to testing and production while keeping changes traceable and recoverable.
This guide compares common branching models and shows how to apply them with practical Git commands, CI/CD controls and troubleshooting steps.
What Is a Git Branching Strategy?
A Git branching strategy is a set of rules that explains when branches are created, how long they remain open and how changes are merged. It gives developers and operations engineers a shared workflow for features, bug fixes, releases and production hotfixes.
A useful strategy answers these questions:
- Which branch represents production-ready code?
- Where should developers create feature branches?
- Which tests must pass before a merge?
- Who reviews pull requests?
- How are releases tagged?
- How are urgent production fixes handled?
- Should commits be merged, squashed or rebased?
Branches are pointers to commits, not complete copies of a project. Creating a branch is therefore fast and lightweight.
git switch -c feature/payment-validationThis command creates feature/payment-validation from the currently checked-out commit and switches to it.
Why Do DevOps Teams Need a Branching Model?
DevOps teams need a branching model to connect source control with automated testing, security checks, deployments and rollbacks. Without consistent rules, pipelines may deploy unreviewed code or build different results from unclear branch states.
A practical model supports:
- Small and reviewable changes
- Automated CI checks before merging
- Clear production release points
- Fast rollback using tags or previous commits
- Controlled access to protected branches
- Reliable audit history
- Parallel development without unnecessary conflicts
The branching model should match the delivery process. A team deploying several times per day usually needs short-lived branches, while a product maintaining multiple supported versions may need release branches.
Students building deployment projects can combine these practices with the pipeline exercises described in AWS DevOps project ideas.
What Are the Main Git Branching Strategies?
The main strategies are GitFlow, GitHub Flow, trunk-based development and release branching. Each model handles integration and releases differently, so there is no single strategy suitable for every team.
| Strategy | Main branches | Branch lifetime | Best suited for | Main risk |
|---|---|---|---|---|
| GitFlow | main, develop, feature, release and hotfix | Medium to long | Scheduled releases and multiple release stages | Complex merges and branch drift |
| GitHub Flow | main plus feature branches | Short | Continuous delivery and web applications | Requires strong automated testing |
| Trunk-based development | main or trunk, with very short branches | Hours to a few days | Frequent integration and deployment | Incomplete work needs feature flags |
| Release branching | main plus versioned release branches | Depends on support period | Products supporting multiple versions | Fixes must sometimes be applied to several branches |
How Does GitFlow Work?
GitFlow uses separate branches for ongoing development, release preparation and production code. It can help teams with planned release cycles, but it introduces more merge operations than simpler workflows.
The usual branch roles are:
main: production release historydevelop: integration branch for the next releasefeature/*: individual features created fromdeveloprelease/*: release testing and stabilisationhotfix/*: urgent fixes created frommain
GitFlow diagram in words
Imagine two horizontal lines. The upper line is main, containing production releases such as v2.0.0 and v2.1.0. The lower line is develop; feature branches move away from this line and return to it, while a release branch moves from develop to both main and develop after testing.
Feature workflow example
git switch develop
git pull --ff-only origin develop
git switch -c feature/order-api
# Edit and test the files
git add src/order-api.js tests/order-api.test.js
git commit -m "Add order validation endpoint"
git push -u origin feature/order-apiAfter review, the feature is merged into develop. When the release scope is ready, create a release branch:
git switch develop
git pull --ff-only origin develop
git switch -c release/2.1.0
git push -u origin release/2.1.0Only release-related fixes, documentation and version updates should normally enter this branch. After validation, merge it into main, create a tag and merge the final changes back into develop:
git switch main
git pull --ff-only origin main
git merge --no-ff release/2.1.0
git tag -a v2.1.0 -m "Release version 2.1.0"
git push origin main v2.1.0
git switch develop
git merge --no-ff release/2.1.0
git push origin developA CI/CD platform can deploy only tags matching a controlled pattern such as v*. This prevents every commit on develop from becoming a production release.
How Does GitHub Flow Work?
GitHub Flow keeps main deployable and uses short-lived branches for each change. Developers open pull requests, run automated checks and merge approved work back into main.
Despite its name, the workflow can be used with other Git hosting platforms. Pull request terminology may differ, but the model remains the same.
GitHub Flow diagram in words
Picture one straight production line called main. A small feature branch leaves the line, receives a few commits and returns through a reviewed pull request after all CI checks pass.
git switch main
git pull --ff-only origin main
git switch -c fix/cart-rounding
# Make the correction
git add .
git commit -m "Fix cart total rounding"
git push -u origin fix/cart-roundingThe pull request pipeline could run:
- Formatting and lint checks
- Unit tests
- Dependency and secret scanning
- Container image build
- Integration tests
- Deployment to a temporary test environment
After approval, the team may use a squash merge so the entire pull request becomes one commit on main. This keeps the production history compact, although detailed branch commits remain visible in the pull request system.
GitHub Flow is effective when the team can release small changes safely. It becomes risky if main is not protected or if tests are slow and unreliable.
What Is Trunk-Based Development?
Trunk-based development requires developers to integrate small changes into one main branch frequently. Teams may commit directly to the trunk or use branches that usually last no more than a few days.
A typical workflow uses:
- A protected
mainbranch - Small pull requests
- Fast automated tests
- Frequent integration
- Feature flags for incomplete functionality
- Automated deployment and rollback
Trunk-based diagram in words
Visualise one long line named main with many small commits. Very short side branches leave and rejoin the line quickly, rather than remaining separate for an entire release cycle.
A feature flag allows incomplete code to be merged without exposing it to all users. For example, an application might read an environment variable:
ENABLE_NEW_CHECKOUT=falseThe code can be deployed while the feature remains disabled. However, feature flags require ownership and cleanup; obsolete flags should not remain permanently in the codebase.
Trunk-based development does not mean bypassing review. Branch protection, required status checks and peer approval can still be enforced while keeping branches short-lived.
When Should Teams Use Release Branches?
Release branches are useful when teams must maintain more than one supported software version. Each version can receive controlled bug and security fixes without including unfinished work from the latest development line.
For example:
main
├── release/2.4
└── release/3.0Suppose a security correction is required in both supported versions. Make the fix on one appropriate branch, verify it, and then use git cherry-pick only when the same commit can safely apply elsewhere:
git switch release/2.4
git pull --ff-only origin release/2.4
git cherry-pick a1b2c3d
git push origin release/2.4Cherry-picking copies the selected change as a new commit. It may cause conflicts when the two versions have different code structures, so each target branch still needs its own tests.
How Should a Team Choose the Right Strategy?
Choose a strategy based on deployment frequency, test automation, release controls and the number of versions being maintained. Use the simplest model that satisfies the team's operational and compliance requirements.
| Team condition | Practical choice |
|---|---|
| Frequent cloud application deployments | GitHub Flow or trunk-based development |
| Strong CI with reliable automated tests | Trunk-based development |
| Scheduled product releases with formal testing | GitFlow or controlled release branches |
| Multiple supported software versions | Release branching |
| New team with limited automation | Short feature branches with protected main |
Avoid choosing GitFlow only because it has more branch types. Extra branches create extra coordination, merge and maintenance work.
A team learning how Git connects with build, test and deployment services can develop these skills through an AWS DevOps course. Infrastructure repositories also need branching controls, particularly when working with shared state and reusable code; see the guide to Terraform modules and remote state.
What Branch Protection Rules Should Be Applied?
Branch protection rules should prevent unreviewed or failing changes from reaching production branches. The exact settings depend on the Git platform, but the policy should be clear and consistently enforced.
For main, consider requiring:
- Pull requests instead of direct pushes
- At least one independent approval
- Successful unit and integration tests
- Security and secret scans
- Resolved review comments
- An up-to-date branch before merging
- Signed commits where organisational policy requires them
- Restricted permission to modify protection rules
Do not store cloud access keys, passwords or private keys in Git. If a secret is committed, removing the visible line in a later commit is insufficient because the value remains in history. Revoke or rotate the credential immediately, then use an approved history-rewriting procedure if required.
How Should Merge, Rebase and Squash Be Used?
Merge preserves branch history, rebase moves commits onto a new base, and squash combines several commits into one. Teams should select a default method and document exceptions so repository history remains understandable.
| Method | Result | Appropriate use |
|---|---|---|
| Merge commit | Preserves branch structure | Release and long-running integration branches |
| Rebase | Creates a linear history | Updating a private feature branch before review |
| Squash merge | Adds one consolidated commit | Small pull requests with many temporary commits |
To update a personal feature branch with the current main branch:
git fetch origin
git switch feature/order-api
git rebase origin/mainIf the branch was already pushed, a successful rebase changes commit IDs. Update the remote carefully:
git push --force-with-leaseUse --force-with-lease, not an unrestricted force push. It refuses the update if the remote branch contains work that the local repository has not seen. Do not rebase a shared branch unless the team has explicitly coordinated it.
How Do You Resolve Common Branching Problems?
Most branching problems come from stale branches, conflicting edits, incorrect branch bases or unsafe history changes. Fetch the latest remote state first, inspect the commit graph and then choose a recovery method.
Problem 1: Merge conflict during rebase
Git may display:
CONFLICT (content): Merge conflict in src/config.js
error: could not apply 8f21abc... Update configurationOpen the file and find conflict markers:
<<<<<<< HEAD
current branch content
=======
incoming commit content
>>>>>>> 8f21abcEdit the file to the required final content, remove the markers and continue:
git add src/config.js
git rebase --continueTo cancel the complete rebase and return to the earlier state:
git rebase --abortProblem 2: Feature branch started from the wrong base
First inspect the graph:
git log --oneline --graph --decorate --allIf the feature should be based on main but was created from develop, rebase only the feature commits:
git rebase --onto origin/main origin/develop feature/my-changeConfirm the commit list and run tests before pushing.
Problem 3: A local branch was deleted accidentally
Use the reflog to locate the previous branch tip:
git reflogExample output:
72ac411 HEAD@{0}: checkout: moving from feature/api to main
19bd822 HEAD@{1}: commit: Complete API validationRecover it with:
git switch -c feature/api-recovered 19bd822Problem 4: A bad commit reached main
On a shared production branch, use git revert rather than rewriting published history:
git switch main
git pull --ff-only origin main
git revert 4d5e6f7
git push origin mainThe revert creates a new commit that reverses the selected change while preserving the audit trail.
What Does a Practical Team Policy Look Like?
A practical policy defines a small number of enforceable rules rather than documenting every possible Git command. It should align repository permissions, code review and CI/CD behaviour.
Example policy:
1. main must remain deployable.
2. Create branches from the latest main commit.
3. Use feature/, fix/ or hotfix/ branch prefixes.
4. Keep pull requests small and focused.
5. Require review and successful CI checks.
6. Squash normal feature branches when merging.
7. Tag production releases with semantic versions.
8. Revert failed production changes; do not rewrite main.
9. Delete merged branches.
10. Never commit credentials or generated secrets.A useful branch name describes the purpose without becoming a sentence:
feature/add-health-endpoint
fix/session-timeout
hotfix/payment-callback
chore/update-base-imageSummary
A good git branching strategy reduces integration risk without creating unnecessary process. GitHub Flow and trunk-based development suit frequent delivery, while GitFlow and release branches can support scheduled or multi-version releases.
Whichever model is selected, protect production branches, keep changes small, automate tests, tag releases and document recovery procedures. The workflow should help code reach production safely rather than add branch types that the team does not need.
To practise Git, CI/CD, AWS deployment and infrastructure automation in guided labs, enquire about AWS DevOps course batch details.
Reviewed by Network Rhinos DevOps trainers.
