Version Control & Branches Strategies – Concepts & Best Practices
The last month (March 2020) it was the 20th anniversary of my professional career. I had many software
development positions but
as a Solution Architect, Release/Delivery Manager, DevOps and Development Process
Manager, positions that are related to this post, I gathered a lot experience in the important thing of
coordinate and manage the whole development process to deliver a successful project.
The version control of code and the branches strategies for any development project (code management) is a vital and it’s the heart of any development process. The value that it provides is often undervalued and misunderstood.
Having a poor code management leading to poor implementations, bad practices and missed opportunities.
Six years ago I wrote a post related to branching strategies (today I think I would say it is obsolete, but not so much), due to a situation I found myself in a young company (young in knowledge) and I was even ashamed to write about it. But then I dedicated by myself to change things and I was given a promotion and gave great value to the company. OLD POST (the real post was published in my old blog website in 2014). In this post I formulated a new strategy called “branching by environment”.
The evolution in new architectures, new teams distribution, new types of software, infrastructure and devices, made a new evolution on code management and include new security and DevOps paradigms.
Today, in the digital era, the software is a important part (often the main) of any business success. The way that the code is developed, manage, deployed and distributed, has never been more critical than before.
First of all, I want to talk about source code control/versioning. Because is 90% common that any team, inherit source code control tools and processes that never or have not been reviewed in a serious way before or that not be the right option to the new one.
Also, as part of the DIGITAL TRANSFORMATION, is important to review the old processes and tools of any management project. Products are now more complex than before, also required different and several software and component integrations, that need another vision to be released. In favor of not evolved teams I can say that it’s something that is green, but in the mayor cases, best practices have been compromised due to lack of functionality in tools, the obsoleted tools used, and the competitivity for delivered a new value and new customer satisfaction.
To manage code is important a few thing:
*- Multidisciplinary teams work together around the world
*- Delivery software (without issues) when is
required
*- Evolve the software, the code and the projects in a clean way
*- Testable code
*- Code
Quality and best practices management and control
*- Maintainable code (easy way to make changes and fix
bugs)
*- Version history and clean rollbacks
*- Code backup
*- Merge versions and features easily
*-
Traceability
*- Changes audit
*- Easy setup (of environment, project and products versions)
*-
Automation of development process (versioning, deploy, rollback, testing, integration, merging, etc)
*-
Isolate new features or versions
*- Code review
*- Code Analysis
*- High availability and cover
disaster
*- Clean deployment and continuous deployment
*- Continuous integration
I think these concepts are topics that each developer, manager, architect, tester, automation, devops, and
any development professional profile knows, but that none apply or do in the best (or optimal) way.
So, I want to help with this post to evaluate what strategy is the most optimum to you:
Version Control and Best Practices
A version control is a software that allow you to manages changes on files over time. It’s an important and vital
component of your development process. Allow to the teams to track the code changes, see the revision history
for the code, and revert to previous versions if is needed.
Also, you can isolate your work until it’s ready,
and quickly find issues or bug fixing. Help streamline the development process and provide a centralized/shared
source for all your code.
The main propose of a version control is enable to multiple people work together in a same code of a project. Is like a database of your code project progress. The part that manage the versioning is the repository and the part that each user have to make the changes is the working copy.
It’s important to have a version control in a development project to keep safe the code and collaborate along the teams.
Depending of the version control type or the version control strategy we can have different ways to do that.
The main premise is that the work of each team member not interfere the work of the other members.
The second premise is that the version control would be the insurance against data loss.
The third premise is that the version control must track every change on the code to allow the rollback or move on an specific version in the time.
First you need to choose the type of the repository:
Types of repositories
Centralized: It was the first approach, and it evolve in different stages. At the First generation, in a no-internet world (and no-common-distributed-teams), the teams use a powerful server which manage the repository, and the developers use a light client to access the files. When a developer edit a file, it was locked preventing any other change. If another dev did a change, it need to update the file and merge the changes locally and then commit the changes and update its local copy before start any work. All work was shared and controlled in the server, the local copy of each dev it not was tracked. With the evolution of development and large teams, the centralized server was a bottleneck with locking and distribution problems, but at the second generation some other tools and the evolution of client/server communications, allowed to continue working in a centralized way with better locking mechanisms and sharing options.
Distributed: With the boom of internet and distributed teams, began to be necessary, to find a new way to repository the code. With appearance of open source projects, new tools was emerge and the combination of centralized and distributed repositories appeared. The third generation was a local centralized repository by each developer workstation that was shared between the others as a centralized repository.
Centralized-Distributed:
But it was only in the fourth
generation when only a true hybrid approach was used and satisfy the new modern products development.
Now its
common that each dev use a centralized power repository and also have a local repository. A famous and clear
example of that is Git. For example, with Microsoft, you can use the Azure DevOps tool and have a cloud
repository (which can have its folders, branches, versioning, components, etc.) and each developer will have a
local copy as a repository with a working copy and work locally and then pull and push the changes to the
centralized version between local and server repository.
The most important thing is choose the best option that can be used in your development process. Is important to
estimate costs, licensing, the team distribution, the software versioning, the isolation needed to work, and the
tools to deploy and merge the code and of course the type of project/software.
Repository Structure
Secondly, you need to evaluate the structure of your repository. In this days the repository is strong-related to
the versioning control tool and the workflow you use, and is very common to use distributed repositories.
Is
important to separate logical units, components, utilities, project layers in the same repository but in
different folder structure.
Check-in
The check-in/commit/submit is the operation to store a new record on the repository with a version of one or more files. Each check-in have a identification, a source, a date, an user and a comment (maybe some other data in particular tool).
A bad strategy on check-in slows down productivity. To make a health repository you need to follow these best practices:
*- Atomic check-ins:
It’s like ACID with
databases: atomic, consistent, isolated and durable.
*-
Single intent:
It should represent a single purpose. If you fix 5 bugs, you
should have 5 check-in, no one check-in of all of them. The best practice is to relate your check-in with your
assigned task.
*-Narrow scope:
If your changes have, for
example, a changes in a database and in a part of code, it should be split in two check-ins.
*-The description explains the “Why” of the change:
The
description of the check-in should explain the reason of the change.
*-Be Consistent:
The check-in should not make the project
corrupt.
*-Be Complete:
The check-in should not be
partial. Maybe in your environment works, but a partial check-in maybe break the work of another team member or
another environment. For example, you check-in the changes in code, but forget the settings or the database
part.
*-Code review:
Before a central/shared repository
check-in, is a good practice to put your code in review. Using a review system or pull request. Using reviewers
is a great way to get another point of view of your changes and detect early bugs, possible inconsistencies or
bad practices.
*-Traceability:
In addition of the check-in
information is important to related your work with the tracking systems or management system to related your
changes and check-ins with the work, audit and reviewing.
*-Be
Reversible:
The check-in should be removable or rollbackable alone, as a piece of unit.
*-Frequently:
Check-in frequently to
make your changes visible to the rest of the team.
Resolve Conflicts & Merging
When different devs make changes on their working copy of same files or someone combine two working
copies and need to decide which change is the winner on the repository, is need to do a
conflict resolution. Modern tools do the resolution automatic, but in old tools or in a particular
situation when the repository can’t resolve automatically, is necessary the human interaction to resolve the
conflict.
In the automation way, usually the tools compare the head of commits, the time of the change, and
in modern tools some AI decide for the best option. The files that are not modified in both parts, be merged
automatically.
Branching
A branch is a copy of the main code to work parallel and isolated environment. Branching is the practice to do this copies to retain the original work and stability and allow parallel development, isolated testing and working, facility to bug fixing, releasing, deploying, and versioning. Also allow the integration of different features and versions.
In an ideal world without issues, errors, bugs, etc, no branches would be needed. But in the development process is not the case.
There are many and varied branching techniques and strategies. Is very important to choose the right one that best fits your project. Also, you can change the strategy in different moments of your project.
All version controls manage branches. This is because while your project will be released, the team need to still developing and fixing bugs. For example, after a release of your project, the client request a new feature and find 5 bugs too, so, the team need to work with this bugs in parallel and with the feature too and also maintain the original version to release a version if is needed. Your team will create 6 branches to work and after the work done, the changes will be merged to a new release (or several releases).
But in projects with few developers as in those with many, branching needs to follow a strategy to avoid serious problems. Spreading the changes is not an easy task, and without guidance, strategy and good practices it can be a strong headache or the loss of changes, new bugs, bad conflict resolution or a loss project.
Branching Strategies
The goal of a branching strategy is to coordinate the development process work, build clean releases, continuous integration, continuous deployment, deployment automation, move between states of your code, fast release and rollback, clean test, enable parallel work, optimize productivity, support versions and patches.
Some teams create a lot of branches to “manage” the work but often is not the best approach. If it’s the case it’s the responsibility of the experiment team member to educate these people. The goal of branching strategy is to give us a easy no-headache development and delivery process.
Is important to communicate to all teams the strategy and why each step is adopted for the strategy, because the strategy in this modern agile and dynamic world change and evolve more frequently.
The strategy often depends of the type of software product, how we release the product, what type of deployment process we follow, what is our testing strategy, the type and the needs of the client, the experience of the team, etc.
There are some patterns of branching strategies that solve common problems already known:
Codeline/Mainline Branching
Some people confuses this strategy with main centered or trunk based strategy and use this name to this another strategy in books or blogs. Also for streams branching strategy.
In this strategy, we have one main branch/line which represents the stable version and live forever. When we start the project we create a main branch to start to commit all team code. When the first release comes, we create a new branch called “Release 1” and freeze/block the main branch. The code in Release 1 is the first release of the product. If any bug appears in the release, the team continue working on the Release 1 branch. Before a new release comes, we merge all Release 1 branch to the main branch and then create a new branch for the new release, could it be “Release 1.1” or maybe “Release 2”. We have the “stable” version on the product on the main branch and the released version on the release branch. If some bug appears on the release, we continue working in the release version. If any feature or new develop is required, we create a new branch with the release name from main branch. Before the next release, we merge the previous release with the new release in the main branch. In some case, some teams merge the previous release branch to the current release branch to have all the bugfixing in the current release branch and then merge to mainline.
Advantages:
In a small product or smalls teams or single
developer project could be enough.
Isolate bug fixing
Isolate features
Isolate releases
Disadvantages:
An only branch for fixing or development could
be a problem.
An only branch for fixing or development couldn’t isolate the testing/QA environment.
Can’t
allow multiple large teams working together.
Can’t allow a clean continuous deployment/integration flow.
A
rollback with parallel working could be a mess.
Block the team development process on releases.
The
mainline could be a mess with a big and slow merge every time a release is needed.
Any small disorganization
in the team or lazy merges could destroy the strategy.
Too many branches complicate the release and merge
work.
A perfect estimation and plan is needed.
Codeline/Mainline Cascade Branching
This strategy is an evolve of the previous one.
To prevent some problems of previous strategy some teams
decide to create a branch per release and develop and fix in the same branch and then use this branch to release
the product. In this case the team never merge to mainline and always create a new branch per release.
Advantages:
In a small product or smalls teams or single
developer project could be enough.
Few branches.
Clean rollback (but stop work).
Disadvantages:
An only branch for fixing or development could
be a problem.
An only branch for fixing or development couldn’t isolate the testing/QA environment.
Can’t
allow multiple large teams working together.
Can’t allow a clean continuous deployment/integration
flow.
Block the team development process on releases.
Slow development (non agile delivery).
A perfect
estimation and plan is needed.
Main centered Branching
In this strategy we have a main/trunk branch line to have the last version of the product. Any branch line is a
child of main or a child of a main child. The idea is to have a releasable and main line to track all product
changes but with the flexibility to create any child branches you need.
First, before a test environment
deploy the team work in a main branch. After the first test environment deploy, we create a new branch called
for example, “Development 1”. All work is integrated on Development 1, so, for each task and bug we create child
branches from Development 1. When a release 1 is needed we merge all tasks and bugs to Development 1 and after
that, we merge to main/trunk line. For the release we create another branch from main called “Release 1”. To
continue we close Development 1 branch and create a new branch called “Development 2” and create any branch
needed to each tasks and bugs. Before a new release, we merge all work to Development 2 to test and then to have
a releasable version merge Development 2 to main. When release the version we create a new branch called
“Release 2” and we freeze the Release 1 branch. To continue repeat the same process for each development cycle.
Advantages:
Few branches per development cycle.
One branch
for all versions and work.
Clean rollback to any state of the main line.
Clean rollback or re-base to any
release.
Concentrate the testing and a QA/Staged version on one point to code review, testing and ensure
quality version.
Preserve separated release for contingency.
Isolate tasks/bugs work per dev or small
teams.
Disadvantages:
A one point to test and validate the work could
be a mess.
A one point to test and validate the work could block the future work.
The teams (quality,
testing, review, developers, devops and release) wait to a clean version to continue working.
The versioning,
deployment and release always is centered in one point that could be a blocker.
Fixing and develop could be a
problem in the current development branch if the team have lazy merging or blocker or delay in fixing or
developing.
Milestones Branching
This strategy is particular for cases when the team wants to have a main branch and create special branches for
each milestone moment . For example, the team start to work in a main branch. Before the release, create a new
branch called “Milestone 1” for the new version and freeze the main branch. The Milestone 1 is released and any
bug reported is fixed in this branch. On the main branch the team continue the work and for a new release the
team create a new milestone branch. The milestone branch fixes never be merge with any other branch. This
strategy isolate any release in milestones and if the team need to merge a bug fix from another milestone to the
new one or another, just refactor the code in the current milestone (in some cases just copy the code or improve
the bug in the new milestone). Sometimes the bugs are reworking or refactoring.
This strategy is ideal for
teams with an abstract idea of product/code evolution. In some product versioning (for example, products that
releases a version by a year or a period) the bugs are fixed in the main branch and the milestones branch never
touch after a release.
Advantages:
Only branches for each release.
Separate
versions of products.
Prevent merges.
Create a branch to release and no block the main branch to continue
working.
Isolate each release.
Prevent inheritance of branches and allow to find the particular
version.
Support different and several release at the same time.
Disadvantages:
Is not an option for the most common project, is
particular for prototypes, demos or versions products.
Cannot isolate dev work.
Cannot isolate
testing.
Cannot create different deployment continuous flows.
If a release have a big issue (it can happen
if the quality fail, or if you tray to develop a standard product but not work in all environments) maybe the
team need to merge the fix to the main branch or deprecate a version or the wrong release (the deprecate option
is the common option and the team rollback the changes in the main line and works in fixing in this line and
then create a new milestone branch for the new version).
Trunk-based Branching
Maybe this is the most famous strategy, because in the old repository or old tools was the way to flow the code
(also in the old centralized repositories). This strategy start and maintain all the code from the “trunk” main
line. For example, the team star to work in the trunk main line, check-in theirs changes and when a release is
needed the team create a new branch called “Release 1”. After the release the new developments continue in the
trunk line and the bugs are fixed on the release branch, after the fixing are accepted they are merged to the
trunk line. If any new feature or experimental development is need to isolate (maybe a new module development) a
new branch is created. But the common way is to develop in the trunk. And with a new release, the team create a
new branch called “Release 2” and the flow continue in the same way. So, we have a stable version in one line,
all bugs are fixing in release branch and then merged to trunk and any developed maintain the same line and
experimental developments are in a new branch. This require an experimented team, an agile work, and continuous
merge, review, integration, testing and deploy.
For some moment in the history of development this strategy
was ignored but in this time has acquired new value. Facebook and Google used this strategy for all products.
Some teams use this strategy combined with temporal branches and pull request (the tools allow this flow in a
low cost option).
Advantages:
Real time feedback
Better quality (one line of
production will be stable to continue working)
Shared code/changes in real time
More collaboration
Push
the team to be agile
Easy continuous integration and continuous deployment.
The code that broke the trunk
be priority.
Real time visibility of the flow of code.
Better reviewing.
Less commits and
history.
Isolate fixing and releases.
Eliminates unnecessary branching.
Minimize merge conflicts and
lots of long live branches.
The team move fast.
Disadvantages:
Need experienced team
Poor tool poor
strategy.
If the team is not agile and works as a agile team, the bottlenecks will be repetitive.
Lazy
commits mismatches the work.
Poor quality broke the main line.
Poor fixing broke the main line.
Cannot
isolate developments.
Multiple blocks or locks.
Poor quality code commits make a collisions and a
bottleneck which stop all the commits (fixed with development branches).
Poor or slow code reviewer, blocks
the work in the trunk.
Task/Story/Feature Branching
This strategy takes notice in multi-large teams around the world, first in open source contribution projects and
then in project with offshore teams or distributed teams that contribute to a core/main team. For example, the
core team start a project in a main line and any tasks, story or feature assigned to other team is developed in
a new branch. Each branch is child of the main branch.
After each team or developer end their work, do a pull
request to merge their changes to the main line. The core teams evaluates, test and review this pull request and
when it is approved the code is merged to the main line. For the releases exists two options, some teams creates
new branches of releases from the main line, and other just tag the main line to released.
Advantages:
Isolate tasks and bugs.
Few branches and
merges.
Fast CI/CD.
Could be scalable to features branches or teams branches.
Less conflict
resolutions.
Disadvantages:
Lazy merge, lazy commits,
or long live branches could be a mess.
If the team have a poor stories/bugs/tasks/feature management, the
strategy will be poor too.
Stabilization of code could be repetitive or recurrent.
Conflicts on main line
could blocks teams work.
A merge or a lot of pull requests merged at same moment could in-stabilize the
code.
A devops or deployment issue could block the main line.
Featuring Flag Branching
This strategy is a variant of the previous strategy. To prevent long live branches of features (and sometimes for partial fixed bugs), the code is merged on certain period of time and if the work is not finished the feature is flagged to disabled. When the work if finished or reviewed or tested, the flag is enable to put up the feature. This strategy usually is used in combination of previous strategy to fix some lazy branches.
Advantages:
Isolate tasks and bugs.
Few branches and
merges.
Fast CI/CD.
Could be scalable to features branches or teams branches.
Less conflict
resolutions.
Prevent long live feature branches.
Disadvantages:
If the team have a poor
stories/bugs/tasks/feature management, the strategy will be poor too.
Stabilization of code could be
repetitive or recurrent.
Conflicts on main line could blocks teams work.
A merge or a lot of pull requests
merged at same moment could in-stabilize the code.
A devops or deployment issue could block the main
line.
A lot of flags could be a problem.
A lot of disabled and obsolete features.
Code that is never
updated again and remains hidden.
Features that already exists are coded again.
Releases Branching
This strategy is an old and obsolete strategy. Is similar to milestone strategy but with the difference that in this strategy the branches are created to store a version release of a same product. Is used when a company sell a product with different features by version and maintain different versions on each client.
Advantages:
Only branches for each release.
Separate
versions of products and evolution.
Prevent merges.
Create a branch to release and no block the main
branch to continue working.
Isolate each release.
Prevent inheritance of branches and allow to find the
particular version.
Support different and several release at the same time.
Product version individual
evolution.
Disadvantages:
Is not an option for the most common project,
is particular for version products.
Cannot isolate dev work.
Cannot isolate testing.
Cannot create
different deployment continuous flows.
If a release have a big issue (it can happen if the quality fail, or
if you tray to develop a standard product but not work in all environments) maybe the team need to merge the fix
to the main branch or deprecate a version or the wrong release (the deprecate option is the common option and
the team rollback the changes in the main line and works in fixing in this line and then create a new milestone
branch for the new version).
Staging Branching
This strategy is used when the team have a non-versionable product.
Usually used in live/online/high demand
products. For example, a website application that give an online service 24/7 for end-user customers (maybe a
homebanking website). In this case, any bug fixing or new feature is deployed and the website is continuous
updated.
For this strategy, the team works in a main line branch and have any “staged” branch that need to
merge the next update and to review and test before go live. For example: Main-QA-Live
Advantages:
One main line to developed and fix having an agile
flow.
Prevent unstable code in production.
A branch to review and gain quality.
Block bad code and
focused on fix issues.
Live/production branch to use in critical bug fixing to separate the code of low
branches.
Disadvantages:
Cannot isolate development
code.
Cannot isolate fixing code.
QA branch have a lot of merges
QA could block a feature or fix if
the environment is unstable.
No version/release branch (only one product and only one rollback)
Environment Branching
This is a strategy to separated the code on each stage of the deployment and delivery process. The team have a
main/live/production/stable branch line. Then with any commit the team create a Stage branch that represent the
staging or preproduction environment. Then create a QA/Testing branch for testing and quality proposes (some
teams need or use a UAT branch between QA and Stage). Then create a development branch and finally create a
features/fixes branches.
The “main” branch for development is the development branch, when a new feature is
started, the dev create a new feature/bug branch. After end the work, the dev or a release manager merge the
candidate changes of the release to development and do the unit testing and code review. When the code is
approved by the architect or by the release manager, the code is merged to QA branch. When the QA team approved
the version, the release manager merge the code to stage branch and use a copy of production data to validate
the version with a real version. If the version is approved the release manager merge the code to the main
branch. The deploy could be automated to deploy on each environment. If the team need more environment, the team
could create any branch is needed and each one need to have a parent and a child branch (process flow
environment relation). Maybe you could need two QA stages or two Stage branches, or use development branches for
each team (maybe in this case the teams work in different modules or component of the product).
Advantages:
The code is reviewed and deployed in different
stages to be approved and to guarantee a better release version.
The issues and bugs could be detected
early.
Isolate features and bugs.
Isolate the code to have a valid integrated version (reviewed in
development) a tested version (validated and tested in QA) a staged version (validate the new version with
current data and changes in production to guarantee a production version with less issues).
Fast
CD/CI
Disadvantages:
More team process.
More management
(maybe a devops or release manager dedicated).
More merge.
More branches.
More conflict resolution.
Development Branching
This is a small strategy used when the team wants to have a main line to develop and when need a branch to develop a more complex feature or bug, create a branch and merge as fast as can. The releases are tagged on the main.
Advantages:
Real time feedback
Better quality (one line of
production will be stable to continue working)
Shared code/changes in real time
More collaboration
Push
the team to be agile
Easy continuous integration and continuous deployment.
The code that broke the trunk
be priority.
Real time visibility of the flow of code.
Better reviewing.
Less commits and
history.
Isolate complex development/fix.
Eliminates unnecessary branching.
Minimize merge conflicts
and lots of long live branches.
The team move fast.
Disadvantages:
Need experienced team
Poor tool poor
strategy.
If the team is not agile and works as a agile team, the bottlenecks will be repetitive.
Lazy
commits mismatches the work.
Poor quality broke the main line.
Poor fixing broke the main
line.
Multiple blocks or locks.
Poor or slow code reviewer, blocks the work in the main line.
Streams Branching
This strategy is similar to mainline strategy but with the difference of multiple fixing and development
branches. The team have a main line, a release line per each release, and a lot of development branch as is
necessary. Also the changes and features between development branches could be shared or merged.
Advantages:
Isolate bug fixing
Isolate features
Isolate
releases
Disadvantages:
An only branch for fixing or
development could be a problem.
An only branch for fixing or development couldn’t isolate the testing/QA
environment.
Can’t allow multiple large teams working together.
Can’t allow a clean continuous
deployment/integration flow.
A rollback with parallel working could be a mess.
Block the team development
process on releases or in merges.
The main line could be a mess with a big and slow merge every time a
release is needed.
Any small disorganization in the team or lazy merges could destroy the strategy.
Too
many branches complicate the release and merge work.
A perfect estimation and plan is needed.
Integrations Branching
In this strategy the team have a main line branch and create a branch for each feature. When a new release is coming, the team create a new parallel branch from main line to merge all included features. If the merge, review, test and deploy is ok, the integration branch is merge to main line.
Advantages:
Isolate features and bugs
developments.
Integrate the version before a release.
Disadvantages:
Too branches
Too merges
Slow release to
production.
Blocks on integration merge.
GitHub Flow Branching
In this strategy the team only have a main branch line and create branches for each new feature or isolate dev
development/fixing.
Is published by GitHub on 2011. Is commonly used with collaboration/open source projects.
The main line represents the stable/deployable/releaseable version. For each new development or fix the dev
create a new branch, work in this branch and dev start a pull request. When the pull request is approved by the
community the branch is merged to the main line and a new version is available to release (often, after pull
request approve the version is released). GitHub use this flow in their repositories.
Advantages:
Last commits/version ready to continue.
Fast
CI/CD.
Simple.
The best for single/online/live versions to maintain (commonly used for opensource
frameworks or libraries)
No branches and merges conflicts.
No blockers.
Developers isolation.
Easy
to update.
Always fast-forward.
Disadvantages:
Unstable production code.
Bad option to
version products or releases plan
No resolve infrastructure or devops problems.
Long live branches
out-of-date version.
Lazy pull request make branches obsolete.
GitFlow Branching
This strategy takes notice in multi-large teams around the world. Is the most popular with Git. In this strategy exists four main lines branches. One the master line that represent the main source. The develop line that represents the main line of features. The hotfix line that represents the line to do the bug fixing and the release line that represents the releases branches. The first step is create the master branch. From the master branch the team create the develop branch, and for each feature that the team start, they create a branch (feature 1, 2, 3, n…). After the features done, all features are pull requested to the develop branch. With each approve, the code is merged to develop. When the work is finish in develop, the code is merge to release branch to freeze the code to the release. After a correct release the code is merged to master. After the first release the team create the bugfixing line branch to do the fixing and after that the changes would merged to master (and to develop from master, some teams merge directly from hotfix to develop). After a new development cycle the develop branch is merge to release to the new release and the cycle start again.
Advantages:
Branches isolation.
Devs isolation.
Pull
request agile mechanism.
Flexibility.
Clean staged branches (stable version, releases, develop and
fixing).
Agile development cycle
Disadvantages:
Too much merges.
Long live branches
issues.
Rollbacks lost merge and version work.
Complex for small teams
Too much pull request required
too much server process to testing and deploy.
Lazy merge between develop and hotfix equals merge and
integration problems.
More management to integrate and release versions.
In large teams CI/CD integrations
problems.
Forking Flow Branching
This strategy is selected when work in a large teams with public or open source project when the merge of
integrations of all changes of each contributor could be a mess. Each dev have a public repository and when need
other feature fork/clone the feature of another dev in own repository. The “official” public repository is the
main repository. The idea is to isolate the team work from the main/public repository without interfering on the
official repository and no have non-official tracking.
For example, let’s say that Microsoft have a public
repository of one their product called “Azure Cache”. Microsoft decide to include a new feature of another
company that develops cache systems and request to this company to develop this new feature in their product
repository. To maintain the main product stable and the current version live and the new feature isolated
(because include a bag of features that represented the big feature), the other company “forks” this repository
to their own repository and start to work on this. After new changes in public repository the other company
synchronize their repository with the public repository and still working isolate. When the other company finish
a release make a pull request between repositories and if Microsoft approved, Microsoft can merge this changes
to their master product branch or to another branch to still working.
Advantages:
Isolate team work without interfering public/main
repository
Hide minor changes on the mayor changes
Merge different branching strategies
Clean
synchronization
Best option for opensource/public projects with new features by other teams.
Clean
pull-request
Own team policy and control.
Free to choose another branching strategy.
Version
isolation.
Disadvantages:
Lazy up-to-date in related
features could be a mess.
Support Branching
This strategy is used in any other strategy. Is used to give support to special release or version without do
changes in other or current version.
For example, a product that have a 3 versions and the first one only run
in Windows old version. If the team need to give support to this old version, create a new branch for this
support and maintain the version in this branch.
Advantages:
Isolate old version and give support on particular
version without interfering new versions.
Dedicated work.
Compatible with any other strategy
Create new
old version merging new features in old versions.
Disadvantages:
Depend on the problem that resolves, but it have
a low probability of troubles.
Product Version Branching
This strategy of course depends on the products needs but essentially resolve a product different version problem
and it can be used in two ways:
Ahead approach:
In
this case the mayor versions contains the minor versions. Each version open a new branch and bugs must be
detected in the minor version to fix. After fixing all minor version must be merged before the new mayor version
is released. All alive version must be alive in branches until they be deprecated. The team must never do a
backward merge, always be forward. The new features always be in the new version. If the client new a particular
feature in old version, we need to create a new branch to merge this minor version with the feature (we need to
find the commit of the merge of the feature to the main/develop branch).
Multiple approach:
In this case the team decided to have
multiple versions to maintain and add features in any version that particular client need.
The team need to
create a branch from the minor version of the product to develop the feature. After the feature is done and
merged to the minor branch, the feature would be merged to each version is needed. If the team need to fix or
change something for this feature in this version, the team would be create a new feature branch from this
version branch or fix it in the same version branch.
Advantages:
The ahead approach allow go forward with the
product and prevent more bugs.
The ahead approach is more clean, also for the products and the
clients.
Both approach allow isolate versions.
Both approach allow combine another strategy, but the ahead
approach is more clean if is used originally.
The ahead approach is faster and more effective than
multiple.
Disadvantages:
The multiple approach always
have more bugs.
Too much merges in multiple approach.
In multiple approach is commonly that the team do
backward merges.
Too much branches.
Lazy merge and updates causes disasters and blocks.
Slow
development process.
I not recommend multiple approach because cause team stress and a confused
product.
Problematic CI/CD (but you can isolated per version and develop).
Deprecated branches still live
in repository.
Alive released braches version still live in repository.
Mirrored Branching
This is strategy use a main releasable branch and two more main branches, the develop branch and the hot-fix
branch.
Is similar to GitHub flow but with a branch to concentrate the features and a branch to concentrate
the fixes. The name is because in a graph the main branch is in a middle and the features branches are in one
side and the hot-fixes in the other. All bugs are fixed in branch fixes and for each feature the team open a new
branch from develop. After feature done the feature is merged to develop and when features version is done and
release, this release is merged to fixes branch. Fixes branch only receive merges from main branch and do merges
to main branch. If you need to merge a bug to develop branch, first you need to merge to main.
Advantages:
Isolated features between fixes and release
versions.
Easy CI/CD
Less branching
Less merging
Compatible with Pull Requests
More integration
version
Easy fixing
Disadvantages:
Could block
features versions and releases
Could block fixing.
Lazy fixing merge cause disasters
Conclusion
As final conclusion, I can say that this strategies are only pattern to try to fit your project. No one are a silver bullet, but they can help you to follow best practices and prevent common issues on branching strategies. Are more common mixed strategies or modified strategies to fit each project.