Effective branch strategy

Before we get to the branch strategy, we need to understand what’s behind it. That is, in order for the dev team to code together, a repository for code sharing is necessary. Coding is a collaborative effort so having a shared repository, or source control, is imperative to see and track everything that is done to the code. Git is our preferred source control to organize, and modify the code during the development process. During this process the code is organized into a variety of different branches.

Naturally the code begins with a main branch, aptly named “develop”, and as development progresses, additional feature branches are added. Every source control needs a clear branch strategy so the code can grow correctly exactly as you’re likely imagining, a tree. Let’s consider 5 key points to defining a better branch strategy for your development project.

Neat convention in branch strategy

Everyone knows that it’s impossible to get anything done with a messy desk, let alone a cluttered office. Here at Slash, we have a set playbook so to speak for best branch practices when defining branch names because a neat convention for branch naming is a must for your branch strategy. We look to separate things by branch name and purpose; for example: develop, master, release, features and so on.

For example, if we define branch names for the environment of development and release and deploy to the server or to go live, we could start as follows.

First we define the environment:

  • Development environment – an environment that publishes often, more in the day during development so the development team can do integration tests faster before releasing for other stakeholders.
  • UAT environment – an environment that publishes periodically at for example, every 2 days or every demo/sprint, so that the client, stakeholder, and QA can test the product quickly.
  • Staging environment – an environment that publishes the near-live version of the product with the same configuration as the production environment so we can test the integration of all systems as it is a production environment.
  • Production environment – an environment that publishes the live version of the product.

Then we define the correlation of the source control’s branch name to the environment:

    • For each environment, we use a branch:
      • Development environment:
        • Develop branch: For the latest code merged to develop or deploy to the development environment.
        • Feature branch: For feature development branched off the develop branch to build new functionality.
        • Fix branch: For bug fixing on the existing feature that has already been merged to the develop branch.
      • UAT environment:
        • Master branch: For the latest code required to deploy to the UAT environment.
        • Hotfix branch: For critical bug fixing that is required to patch the issue for the UAT environment and potentially be re-released as a tag for the production environment.
      • Staging environment:
        • Master branch: For the latest code required to deploy to the UAT environment.
        • Hotfix branch: For critical bug fixing that is required to patch the issue for the UAT environment and potentially be re-released as a tag for the production environment.
      • Production environment:
        • Tag that starts with version/number: For the latest code freezed for the production environment.

(branching example illustration)

In addition to defining the branch strategy above, to keep things simple and consistent, we should also define the naming convention for the branches which are agreed upon and widely accepted in the team. For example, you name a feature branch as “feature/your-short-feature-title” or “feat/ticket-id-your-short-feature-title” or “feat/ticket-id”. You can employ a different variety of names, but it is something to be agreed upon by the team members.

Once we have clear branch naming, environment and workflow and know what needs to merge to what, the team can operate easily for the daily code push and process activities. It’s also ideal for best branch practices to define other conventions such as:

  • File changed per feature or fix or hotfix branch: We should commit to a considerable amount of files per branch; for example, at most 10 file changes. If there are more than that, consider splitting your single feature branch into multiple branches building different parts that are WIP (work in progress) for your feature which is beneficial for code review later.
  • Relevant Files changes per commit: We should commit relevant files that are changed for a single commit. For example, if you change the language of the web app by adding new language files and adding new words to the menu bar, you should commit those together as one single commit. This makes it easier to understand what changes have been made.
  • Commit message: Short meaningful message to give description of what you commit; it’s like telling a story of what you have done for certain changed files.

Last but not least, you don’t have to do all of those things manually; naturally, people can forget or might not be consistent throughout the weeks or months. We can use some tools to help automate the process or at least give reminders of the rules we set upon ourselves. For example:

  • A Git plugin named commitizen could give us a few questionnaires of what we are committing changes from asking what types of change those files are. For example, document changes, bugs, or feature changes, will ask you to enter a short or long description.
  • A git plugin named pre-commit or husky could be set up to remind the team that “Before you commit changes, by the way you have unclean code in these files and you failed to do the test, please fix it before you proceed…”. 

All of these practices allow us to keep a very neat and tidy naming convention as well as consistency within our branch strategy.

Also Read : 5 Considerations When Launching a Product

Restrictive permission

For our second point we have restrictive permission. I presume it is moderately safe to assume you are acquainted with document or file permission restrictions; for example, like that of Google Docs on Drive. Naturally the same applies for code that is added to the various branches. Who can merge, who can push, which branch can be pushed, and other permission restrictions should be set. It’s also good to restrict certain permissions in order to avoid corner cutting in regards to merging directly and bypassing different quality gates that we set; as well, avoid deploying those bypass changes to the environment in the cloud thru CI/CD. Your best branch strategy needs a clear method of handling the code and related files!

For example, we can set in the Bitbucket, the source control we are using, that no matter who it is, they cannot push their code directly from their machine to the “develop”, “master” and “tag” at all. The only way to merge is to create a pull request to those branches and that pull request has to be approved by at least 2 people, and must have a previous running build passed.

Thorough code review

Now for our third point, thorough code review. As mentioned in the previous paragraph about setting branch permissions to not allow any direct change to the main branch for example, develop branch and to only allow through pull request.

So a pull request is a process of asking to merge your code to the target branch such as merging your feature branch to the develop branch when you have finished your part in the feature. As a requester, you create the pull request in your respective source control, in our case bitbucket, put the meaningful title, detailed description matching the checklist set by the team and assign reviewers to give you feedback, request change to your code or approve it.

As reviewer, on the other hand, you have a responsibility to review the code to match the agreed coding standard and practices of the team. For example, if you see people declaring variables but haven’t used it, you should call it out since it is not a good practice to declare and not use. In the other case, if you see people writing a while-loop code to send out 100 of pending message on the client side, for example, mobile app, to the server after the user re-open the app, you must call this out too since it is an issue for the application and server performance causing the entire ecosystem of the system to stop functioning.

Thus, if there is a problem, it must be corrected before going to be merged to the main branch. However, if the code checks out clean with no issues, it is allowed to be merged and gets uploaded to the main branch. Consequently, the reviewer needs to be your ace in the hole; someone who is going to check the code with the highest standards to ensure a clean branch.

The high standards for code production are necessary so having a thorough and clear code review practice is also warranted. Your development team should follow a code review process, code standard, code best practices, making sure all team members’ code passes the checklist. Consider checking items such as writing up change description, a checklist of breaking changes or feature changes, whether or not you’ve tested it yourself and even if it passed unit testing and quality control. All this meticulous review will help you develop the cleanest code your team is capable of doing.

Continuous integration & deployment

So what’s next after your code in the pull request is approved? The answer is to deploy it! The reason is that we want to streamline the deployment process from code to deploy the environment automatically.

For example, one pull request for a new feature is approved and merged to the develop branch. Imagine, we, as developers, manually do the build of the recent code for 20 minutes, send the built code to the server to deploy in 10 minutes, remote to the server and run script to refresh a new code built in around 5 minutes and those time are dependent on the internet speed and the computer capability of the developer. Imagine, if the same person unfortunately had his computer broken, the build, integration and deployment chain will be broken and need to be delegated to someone else which takes a lot of time and is not efficient.

As a result, we want all of the above actions to be automatic and more importantly to be continuous every time we have the recent code to the specified environment, for example, in the above case, the development environment. To achieve the above goal, we will use the CI/CD tool that usually comes with the source control, for example, Bitbucket has Bitbucket pipeline, Github has github action, Gitlab has CI/CD etc. Moreover, we can use other platform tools such as Circle CI, Ansible, Serverless or AWS Codecommit, Azure devops, Google Cloud Build, or on-premise’s Jenkins and in other cases a more specialized platform for example to build flutter mobile app, which is Code Magic and so on.

The above mentioned tools would have different ways to configure but it stays on the same foundation to help you setup the continuous integration and deployment from coding to the deployed public URL as fast as possible.

Relevant release version

Finally we come to relevant release versioning for having a better branch strategy. File naming conventions can often be overlooked, but are no less important than other aspects of your branch strategy and greater development project. It’s best to create a clear naming plan for the release product, tag release, versioning in relation to the milestone of product release and so on.

Deciding the release version number is easy but deciding the relevant release version to the relevant code to identify the correct product release milestone can be difficult. Assuming the product release milestone has been set for which features are in which releases. For example, we are working on version 2 (v2) of the banking app product. The product team clearly prioritized version 2.1 to introduce new features, for example, allowing employees of a company to apply for a loan directly via the banking app without further approval except the records of salary with the partnered company.

To be able to achieve that, we have to define the proper branch strategy for versioning, we would use a release branch with name, release/v2.1 to merge all the code of the relevant features of employee loan to release. Upon the release date, we proceed to create a tag with name tag/v2.1 from the release/v2.1 to freeze the version v2.1 code to be able to release to the production for public usage.

But the process of getting from the feature codes (developing features) to develop branch (development environment) to master branch(UAT environment) to release/v2.1 (staging environment for v2.1 as a release candidate) and to a production release while sometimes the development team still have to deal with fixing bugs from older versions that are currently live (production release for public to use) for example, v2. The answer would circle back to the foundation of properly creating a convention, to merge features or fix or hotfix to main branches, to continuously integrate and deploy in each respective environment and to release.

So to sum up, a neat convention, restrictive permission, thorough code review, CI/CD and relevant release versioning can all lead you to having a better branch strategy for your code development. Just as you keep your desk and work area clean and organized so too should your team keep the branch clean and organized.

Promsopeak Sean Nuon
Sean Promsopeak Nuon
Lead engineer
Sean is technology-driven and passionate about working with technology that helps people. Now he finds himself as an executive member of Slash, executing the technology operation side from an entrepreneurship point of view. He has over 9 years of working experience dealing with technical problems, project management and team mindset building. He splits time between Solution Architect & Lead developer for enterprise clients and as part of the management team, he helps build future-proof architecture, define quality standards, team culture, and hiring & training practices.
In this article

Explore more resources

ges of Product Development Workflow
6 Stages of Product Development Workflow You Must Follow in 2024
In 2023, it is essential to follow a 6-stage product development workflow. These stages include conceptualization, research, prototyping, testing, development, and launch. Here are the complete details for each step.
8 minute read·
by Kevin Yin Seng ·
September 13, 2023
Ethical Dilemmas in Product Management: Navigating Responsible AI
Ethical dilemmas in product management: navigating responsible AI
10 minute read·
June 19, 2024
Skip to content