Optimizing Development Workflow

The Importance of Synchronizing Work Items and Branch Strategy

Murat Özalp
Bits and Pieces

--

The most important thing I learned from various web-based projects, both big and small, that I have been involved in since 2014 is this:

As a software development project grows, the harmonious collaboration among its various components significantly affects the gears of development.

Perhaps the two most crucial elements forming the most vital parts of these gears are the project’s work items and branch strategy.

Here is a strong or should-be strong relationship between branch strategy and the work boards we use to manage sprints in our project. Let’s evaluate the reasons for this through various scenario situations and then explore what the possible solution could be.

Case 1: Numerous modules and developers

As projects grow, the number of modules and screens constituting these modules increases. In parallel, the number of developers working on each module will also increase. In such cases, the directory structure of the project’s source code should be designed in proportion to the modules. The tasks to be taken from these modules should be converted into the smallest possible units that can be divided.

So, how can we determine if we have minimized a task as much as possible? First, we can examine the effort required and its dependencies. Finally, we need to consider its testability and ensure that it can be concluded with unit and acceptance testing for that small piece of work. This way, we uncover all the requirements necessary to consider a task completed.

Consequently, after opening a task on the board, the responsible developer can create a branch on the repository using the following keywords: the module name and a brief description with the task name.

Example for Case 1

Let’s provide an example for a banking project then.

Assume we have a banking project with multiple modules, such as “Account Management,” “Transaction Processing,” and “User Authentication.” Now, let’s say there is a specific task related to the “Account Management” module, which involves adding a new feature for updating account information. The responsible developer can create a branch in the repository using keywords like “AccountManagement” and a brief task description, such as “UpdateAccountInfo.”

Developers working on the same module would start by creating an AccountManagement branch. They would then create individual branches, like UpdateAccountInfo based on the AccountManagement branch to complete their specific tasks.

Case 2: No One Is Perfect

In a project where not everyone is perfect, tasks may not always be completed within the designated effort or even in the same sprint. Additionally, multiple developers may need to work on the same task.

In such situations, breaking down tasks into smaller units allows you to identify the easier or more challenging aspects of development, enabling you to make accurate assignments to developers and facilitate effective collaboration.

The goal is to always create tasks that can be completed within a sprint and to establish a collaborative board where we can support each other when needed.

Example for Case 2

We have had the branch of UpdateAccountInfo based on the AccountManagement branch. The developer working on the UpdateAccountInfo task realizes during the daily meetings that there is a risk of not completing it within the sprint. They request support for the task. Another experienced developer with available time steps in to assist.

In this scenario, the assisting developer can either:

  1. Open a new task and new branch related to a specific portion of the remaining work, such as ValidateAccountInfoInput.
  2. Create a new branch specifically for providing support on the UpdateAccountInfo task, such as UpdateAccountInfo-Support.

Therefore, the supporting developer will push their changes to the UpdateAccountInfo branch, allowing the initial developer to review the updates and merge them as necessary. Finally, the developer can push all the development on the UpdateAccountInfo branch to the AccountManagement branch.

Case 3: Test vs Release

As mentioned, we create branches for each module, and these branches should be based on the branch that represents the latest release. We can refer to this branch as the “release” branch. The developments made on the module branches should eventually be pushed to a common branch, which will be used for system integration testing (SIT) in the test environment. We can refer to this branch as the “test” branch.

Even if the SIT (System Integration Testing) for development is completed, there may be cases where the development itself is not ready for delivery. There can be various reasons for this, such as changing requirements or incomplete security testing. Therefore, pull requests (PRs) for the release branch should always be sent from the branches associated with the specific tasks. This way, we can avoid code separations and complicated cherry-pick operations, ensuring a smoother workflow.

Example for Case 3

Let’s assume that the Account Management module team has completed three tasks throughout the sprint: “UpdateAccountInfo”, “AccountBalance”, and “TransactionDetail”.

Developments from the AccountManagement branch are sent as pull requests to the Test branch for SIT. However, the UpdateAccountInfo development is not ready for delivery, so we cannot send all the AccountManagement developments to the Release branch together.

PRs to the Release branch should originate from task branches, which are derived from module branches, ensuring that any unexpected developments not present in the Release branch are not pushed.

Case 4: A Shared Branch for Each Module

In the previous scenario, we discussed our PR strategy considering the possibility of not delivering all completed tasks at once. In cases where developments are not sent, there may be shared modules or helper functions used within those developments.

To manage this, we need to do the following:

  1. Create a separate directory in the source code for shared components and functions.
  2. Create a branch on the Module branch where we can develop shared component enhancements.

Example for Case 4

Let’s say we are developing two screens within the same sprint. Both of these screens require the Account Validation process. Therefore, we should perform this development in the shared development branch specific to the AccountManagement module.

Shared Branch: AccountManagement/SharedComponents

As a result, the dependency between the two separate developments will be eliminated. Instead, the development existing in the shared branch will be delivered without exception.

Solution

There is no perfect solution. Please feel free to share your ideas for solutions that are close to perfection :)

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--

Passionate software dev. Let's share knowledge to finding near-perfect solutions!