In this article we will present the most popular branching strategies and their differences, as well as set the scene for teams that want to start using a comprehensive branch naming convention.
Branching strategy
Branches are primarily used as means for teams to develop features giving them a separate workspace for their code, which are usually merged back to the main branch once the new feature is implemented. A branching strategy, therefore, is the strategy that software development teams adopt when writing, merging and deploying code when using a version control system.
Adhering to a branching strategy will help developers to work together without stepping on each other’s toes. In other words, it enables teams to work in parallel to achieve faster releases and fewer conflicts by creating a clear process when making changes to source control.
Branching Strategies
- GitFlow strategy
GitFlow is a branching strategy that uses feature branches and multiple primary branches. It is characterized for the long-lived branches and large commits as part of the merging strategy.
There are 5 types of branches: main (previously called master), develop, feature, release and hotfix
- main: production-ready code, all branches are merged on main after developed/tested
- develop: pre-production code, new features that are being tested
- feature: add new features to the code, cut from develop and merge back once completed and reviewed
- release: prepare release with finish touches and minor bugs separately from main/develop
- hotfix: quickly address changes in main branch, merged to main and develop
Overall it is well-defined and straight forward, but it hides complexity when merging code from development branches to main branch. The two step merging (develop and main) may slow down the development process.
(source: https://skynix.co/resources/navigating-git-branching-strategies-a-comprehensive-comparison)
2. GitHub Flow strategy
GitHub Flow is a lightweight and straightforward branching strategy designed for continuous delivery and deployment. It focuses on simplicity and works best for projects with a single production version. The main branch contains production-ready code (code that is deployable at all times) and feature branches contain new features/bug fixes will merged to main to introduce new work (possibly exist for several days or even weeks).
The main features here are:
- main branch: contains production-ready code
- feature branches: created from main branch to introduce new functionality
- frequent commits and pushes: commit and push changes regularly to ensure progress is saved and visible
- pull requests: create pull request to merge the new code from the feature branch to the main branch
- deployment: once the new code is merged the main branch in deployed
Overall good when there is a single production version, but does not support multi-version codebase and the lack of short-lived branches will make main branch to be multiple heads in front of the feature branch.
(source: https://skynix.co/resources/navigating-git-branching-strategies-a-comprehensive-comparison)
3. GitLab Flow strategy
GitLab Flow is a simpler approach of GitFlow branching strategy that combines feature-driven development with issue tracking. The main branch is the central branch where all development work converges, while optional pre-production and production branches enable thorough testing and stable deployments.
The main features here are:
- main branch: primary branch where all features and fixes are merged
- feature branches: created from main branch to introduce new functionality
- pre-production branches (optional): branches like test and staging for additional test and validation before merging to main
- production branch: a stable branch used to deploy the main branch when ready for production
- version branch: create branches like v1 or v2 to maintain and update different versions independently
(source: https://www.abtasty.com/blog/git-branching-strategies)
4. Trunk-Based strategy
Trunk-Based Development is a streamlined and fast-paced workflow where all developers work closely on a single branch, typically the main branch called trunk. Changes are integrated into main frequently, promoting continuous integration and rapid deployment. Feature branches are short-lived and deleted immediately after merging.
The main features here are:
- main branch: single source of truth, containing production-ready code at all times
- feature branches: temporary branches created for new features or fixes
- pull requests: create pull request to merge the new code from the feature branch to the main branch
- deployment: once the new code is merged the main branch in deployed
(source: https://www.abtasty.com/blog/git-branching-strategies)
Branch naming strategy
Branches should follow a specific best practices pattern to facilitate collaboration among the team. The following pattern needs to be followed in Azure DevOps, as it distinguishes the structure of the branch name into separate directories under Branches section:
<change_type> / <User Story> — <Description>
- prefixes (change type) must be related to the content of the branch
- feature: introducing new feature functionality
- bug: addressing/resolving reported bugs
- chores: maintenance tasks that are not features or bugs (e.g. introduce comments or documentation)
- release: release preparation branch (if we decide to have one)
- work item (User Story) must the one from Azure Board
- description must be descriptive to help team members to quickly understand the purpose of the branch at a glance.
Prefer lowercase and hyphens for better readability
Example: feature/123456-add-new-functionality
In addition, there are tools that can help in setting the branch naming standards up. Some of the most popular tools are:
- Husky: Adds Git hooks to enforce naming rules at pre-commit or pre-push stages, ensuring consistency before pushing changes.
- Commitizen: Focuses on commit message conventions but can complement branch naming standards to keep everything consistent.
- Git Hooks: Native hooks that can be customised to enforce branch naming patterns during commits, merges, or pushes.
- SonarQube: Primarily a code quality tool, but can integrate with Git to enforce branch naming conventions as part of quality gates.
- GitFlow: A branching model that can be enforced with tools in Git platforms like GitHub or GitLab, encouraging branch naming conventions such as
feature/
orhotfix/
. - GitHub Branch Protection Rules: Indirectly enforces branch naming conventions by restricting pushes to specific branches and requiring pull request reviews.
- Semantic Release: Automates versioning and change log generation, often used alongside structured branch naming (e.g.,
feature/
,bugfix/
,release/
) to manage releases automatically.
Code review process
-
raise PR once the new code is completed and push to a remote branch. On each PR:
- provide a meaningful title (as it will be visible in the history of the main branch)
- provide a description that will quickly describe the purpose of the PR (verbalizing the title of the PR)
- provide the US related to this work
- add mandatory tech related reviewers
refer to team member (preferably with content knowledge) to review
then it comes to reviewers’ responsibility to review and provide feedback on the code
Reviewers’ responsibilities:
- verify language/code related patterns and security risks
- verify common patterns are followed between old and new code
- create clear comments describing the area that needs to be altered
- once the comments are resolved, each reviewer needs to state if his/her comments are addressed
Keep in mind that any new code that is about to be merged, needs to have the respective Unit Tests in place (meaning that the Unit Tests will already be part of the code that is about to be reviewed/merged).
Merge policy
Define how changes from different branches are integrated into the main codebase
Types of merging
- direct merge: merge directly into main with all commits from feature branch available on main
- squash merge: combine all commits into one before merging, to keep main branch history clean
- rebase: move changes from feature branch on top of the main branch, creating linear history
Preferably we need to combine squash and rebase, meaning that all commits of the feature branch need to be squashed into single commit and then rebase the main branch on the feature branch and resolve conflicts to keep commit history clean. After resolving the conflicts, a PR can be raised as described above.
How can Trunk-Based strategy and the Merge policy be effective on important aspects
- Discover flaws early: By integrating small changes/features into the main branch (trunk) and run specific tasks as part of the CI (as described above) we can minimize the risk of introducing large and hard to find bugs, as we ensure that every small piece of code merged is not causing any issues/failures.
- Enable fast and smooth CI/CD process: By having the above mechanism in place, we can merge code quickly and safely (as already mentioned) which gives us the necessary confidence to proceed and deploy the new features in stages above DEV and TEST.
- Give some control over what is released when: By combining short-lived branches (and/or a release related branch potentially) with clean commit history, we have the flexibility to point over what is about to be deployed on any stage. A release branch should be the option when a ABN/PROD deployment is about to take place.
- Note: any changes/bug fixes that are implemented on release branch, SHOULD also be available on main branch so a PR from release branch to main needs to be raised
- Easy Rollback: By ensuring that our main branch (trunk) is continuously stable, reverting to a previous working version is straightforward.
Conclusion
In conclusion, effective branching and merging strategies are essential for maintaining streamlined collaboration and minimizing conflicts in software development lifecycle. By choosing the right strategy teams can align their workflows with project goals, team size, and release cadence. Prioritizing clear guidelines for development process, reduces errors, and promotes a cohesive codebase. Ultimately, the success of any branching and merging approach lies in consistent communication and adaptability to evolving project needs.
In case you are looking for a dynamic and knowledge-sharing workplace that respects and encourages your personal growth as part of it’s own development, we invite you to explore our current job opportunities and be part of Agile Actors.
Top comments (0)