Over the past few weeks, many of our masterclasses have centered around a 38-page essay by Martin Fowler about how to dramatically reduce the time teams spend merging dozens of branches together through workflow patterns. In today's issue, we condensed that article (and the masterclasses) by 70% into a roughly 5-10 minute, ten-page outline of the full piece, so you can get all the highlights without spending an hour or so reading and taking notes on Fowler's article.
- First, to make it easier for multiple people to work on a codebase at the same time, each developer in the team should create a copy of it. In order to merge the copies together once they're finished, Fowler recommends relying on a source code control system to record changes made to individual branches as a commit.
- However, Fowler notes that source control systems cannot always tackle all issues, such as textual conflicts. To help avoid textual or semantic conflicts, one in which, for example, two developers on a team give different names to the same variable or function. Fowler suggests using a single, shared codeline, or what he terms the "mainline," that is the current state of the code.
- Whenever you start on a new piece of work, pull the mainline code into your local repo to work on, and update the mainline when you wish to share the code with the rest of the team. Make sure, he says, to pull changes from the mainline into your personal branch at intervals to make sure the product is up-to-date.
- Yet Fowler notes this in itself is not enough; make sure to also keep the mainline branch and others healthy by using Self Testing Code, performing automated checks on each commit to make sure there are no issues with the branch. While it's debated how long you should do this for, Fowler notes how some team successfully separate tests into multiple stages on a Deployment Pipeline, with the first stage -- the commit suite -- lasting for about 10 minutes, to save time on other stages.
- While this process is important for personal branches, Fowler particularly recommends that you use Self Testing Code on the mainline, and build a commit suite for it. Although he notes this may take a lot of time and energy, this is critical to ensure a single commit won't break the whole development process.
The mainline offers the team a view of the software's current state and makes it easier for everybody to integrate by allowing each developer to do so individually.
- Let's say you start working, cloning the mainline into your repository.
- While you work, your co-worker pushes changes into the mainline. When you're ready to integrate, you fetch the current state of mainline into your local master branch to pull in the co-worker's change, and merge those changes.
- If there is no textual conflict, it will be a clean merge; Fowler again encourages the Self Testing Code approach to better manage such conflicts if there is one.
- To complete integration, you push your changes into the mainline, a very important yet overlooked step, Fowler says.
When to use it: Use it if your team is using mainline on the product.
Alternatives to using mainline integration:
- Pull from mainline and merge changes into the personal development branch, but be aware that unless the other team member pushes, others on the team won't be able to see if there are conflicts between your changes and your co-worker's.
- Another alternative: open a Collaboration Branch when you're not done but want to share work with a colleague that you think may overlap.
Create a specific branch for a feature, place all your work on there, and then integrate into mainline when you're done working on the feature.
- Let's say you're working on a feature to add to your site. You will start with the current stable version, pull the mainline into your local repo, and then make a new branch starting at the tip of the current mainline.
- As you work, you'll make a number of commits. You may also push the feature branch to the project's repo so others can see it, while you may also pull from the mainline to see if any of your other team member's changes will affect your feature. You will only be looking at each other's work, at this point, not integrating. Depending on whether or not your team likes to keep all code in a shared repo, you may push your feature branch into it to let other team members see what you're working on.
- When you're done working on the feature, you'll then perform Mainline Integration to add the feature to the product.
According to the State Of Dev Ops Report, top development teams integrate more than poorer performing ones, something Fowler says he's seen personally.
Avoid Low-Frequency Integration, Embrace High-Frequency Integration
- Low-Frequency integration can make it harder as you'll have to make larger, more complicated merges. Smaller merges save time in the long run and are less risky, saving you hours from having to fix an integration down the line.
- It also helps you root out potential conflicts earlier, saving you, again, more time. For example, let's say you and a co-worker are working together. You clone the mainline into your branches, make some local commits but don't push yet. If you two develop conflicts in the initial commits, you won't be able to find it until a merge made much later if you adopt a low-frequency approach while you can opting for the high-frequency one.
- "Increasing the frequency of integration is an important reason to reduce the size of features," Fowler adds, noting doing so also makes it faster to build, deploy it into production, and reduces feedback time.
An alternative to feature branching, those who adopt Continuous Integration integrate each time they've made a solid amount of progress on a feature every day, often many times.
Using this approach, Fowler says you must become comfortable with the idea of reaching frequent integration points with a feature that hasn't yet been built without exposing it in the running system. For instance...
Click here to upgrade to premium to read the rest of the outline.