Speed and flexibility of software development play an important role. However, with a large development team working at the same time, branching and merging code can get messy. These teams need to be provided with a process to implement changes concurrently. An effective branching strategy is a priority in resolving this issue.
A branching strategy is a set of rules that developers follow when writing, merging, and deploying code when using version control. In situations where multiple developers are working and adding changes at the same time, the branching strategy structures the repository and avoids merge confusion. Merge conflicts hinder rapid code delivery and hinder the creation and maintenance of an effective DevOps process.
Thus, the branching strategy creates a clear process for making changes to the system. This helps to solve this problem and provides the ability for multiple developers to work in parallel and independently to release faster and minimize conflicts.
The branching strategy allows to:
- ensure coordination between developers and improve productivity;
- parallel development;
- implement planned and structured releases;
- make changes to the software;
- maintain bug-free code and the ability to quickly fix issues and push changes back into production without interrupting workflow.
The branching strategy is an important working tool. Arbitrarily creating branches in Git by different developers can lead to chaos. A branching strategy will allow to redirect attention to the development process itself, rather than version control.
Branches in Git are represented by tags or pointers. All changes are tracked as a directed acyclic graph, each node of which is a set of changes made simultaneously. Git branches provide developers with the ability to deviate from the master branch and create separate branches to isolate code changes. The default branch in Git is «main branch». The main advantage of a Git branch is its «light weight». That is, the data consists of snapshots series, and each time Git commits changes. It takes a snapshot of the current files state and keeps a link to this one. Such branches are not just copies, but also a pointer to the latest commit.
Basic Git branching strategies:
- GitFlow is a model that shows the ability to develop in a team and individually. At the same time, only 2 main branches (master and develop) accompany the development life cycle. Other branches are temporary, which ensures a permanent order in the repository;
- GitHub Flow is a simpler version. It only has master and feature branches. Consolidating all changes to master and deploying frequently allowed changes to be released immediately, following the principles of production and continuous delivery;
- GitLab Flow – offers a dedicated production branch for managing code release to production. It is possible to configure automatic code deployment from this branch with each change in it. The release is provided through a merge from the master branch to production. With the help of this branch, it is possible to obtain data on the released code version. It is possible to determine the approximate release time by the time the merge commit was created;
- Trunk-based development – an approach that involves development based on a single trunk branch. The key approach features are temporary branches existence (several days), continuous code review (the process of checking and analyzing the code by the developer before release), master readiness to release at any time. This approach ensures conflicts minimization during development, readiness for release without preparation, fast and high-quality feedback on PR/MR.
An example of a merge conflict and its resolution
Let's look at an example of a merge conflict and possible ways to resolve it using QOps to control versions of a Qlik Sense application. Let's take a Qlik Sense application and use QOps to create a source code repository and 2 branches dev1 and dev2 for individual developers. Imagine a situation where each of the developers changed some common element (for example, the background objects color with the output of KPI values).
Since the changes occurred on the same lines at the source level, when merging dev1 -> master and dev2 -> master, a merge conflict occurs in the last variant. Resolving a merge conflict requires deciding which of the options should be present in the reduced version. The VSCode development tool allows to interactively make this decision. However, this puts additional responsibility on the IT specialist who will perform the merging.
There is a risk of receiving from both developers code parts for a common element in a final application that may not be compatible. For example, after a merge, it is possible to get the following result when the first object is set to Accept Incoming and the second is set to Accept Current.
It is convenient to merge source codes using the web interface of version control systems. Below is the progress of a Pull Request on GitHub with a conflict-free merge.
The presence of conflicting changes leads to the output of the corresponding warning and additional information.
GitHub interface allows to resolve merge conflicts in small files, while the user needs to manually edit the source code marked as conflicting and confirm the changes. If this operation can’t be performed through the web interface, GitHub will ask to resolve conflicts locally.
Also, let's resolve the existing conflict in the opposite way. As a result, we get the expected result with the opposite coloring of common elements.