Why We Switched from Single Branch Flow to Pull Requests
As you probably know, there are two ways of dealing with Git development: one assumes that you push everything to master (single branch flow), and the second is all about multiple branches (multi branch flow).
In this blogpost, I would like to share netguru’s story about migrating from one flow to another.
Why Multi-Branch Flow?
Just to remind you of a few things from the past - before 2016 we were true believers in single branch flow. We shared our views in blog posts about the ups and downs of pull request flow. But we can’t be slaves to our own decisions, so we’ve taken another look at how we push our code to the world.
We also felt that our code review process could be improved. We were checking ALL the commits pushed to master, even if they had been changed a couple of minutes after the review. Those commits had to be very small so that we could check them one-by-one and understand what a particular change does. This forced us to be very strict and caused a lot of pain when we had to wrap our head around a series of commits and check them independently, instead of reviewing them as one change to the codebase.
And then there was the problem of delivering multiple different features all at once when one was finished, and the other was still “work in progress”. It was very hard to develop this way, and we had to hack the system using feature flags which weren’t designed with this purpose in mind.
Now we push all our commits to feature branches, we create Pull Requests when they’re ready, and this is where all the good things start to happen:
- We have a condensed code review: only the current code is visible in diff view, we don’t have to deal with the initial version. But, in case we have to dig deeper, a list of all the commits in chronological order is available
- Each comment is hidden after a given line is changed: we don’t have to introduce any additional tool to track if someone has fixed the issue we’ve mentioned
- Work on multiple branches is independent: which could be a bad thing, but most of the time we see this as an advantage - we can focus on our stuff and deliver the feature we need.
Main Disadvantages of Migration
In comparison to single branch flow, we found a few flaws:
- there is some small overhead - you need to create a branch, make sure you name it properly and then create a Pull Request where you have to describe the change
- more communication happens on Github which might be an issue for someone less familiar with this
Additional Tools and Processes
But making changes to branches isn’t the only thing we introduced with the migration to Pull Requests. We introduced some new tools/approaches to our flow so that we can get the most out of it.
Apart from changes in the way we do commits, we’ve also migrated to a docker-based devops stack. It turned out that creating a new environment for the app is quite easy. Thanks to this, with every opened Pull Request - we automatically build an integration environment containing code only from that PR. We use a modified version of Heaven, which builds a fresh app available at a specific URL.
With reasonable seeds (sample data) in place, it’s a really nice way to test things out - we won’t ruin somebody’s data, we can mess with the app and data as we want and make sure it works as expected before we introduce changes to the master branch.
When a dev finishes their work, they just give the QA a green light to test things out in real life. After the QA accepts the change, we’re ready to merge the feature branch to master and deploy it on production.
And yeah, this requires that a fresh set of sample data is created every time a new version of the app is deployed. This a good thing, because it means that our app is ready to be picked up by another developer with minimal setup - we can introduce new developers to the app very quickly.
Prtrade - Slack Integration for Trading Pull Requests in Different Projects
We love Slack, and we couldn’t resist writing an integration for Pull Requests. Our approach might be a little different to that of other teams because there’s a lot of people in our team and a large number of Pull Requests opened every day.
Each Pull Request has to be reviewed by someone before it gets merged. Sometimes there’s no more than 1 dev on the team; sometimes we want a fresh pair of eyes (someone outside the project) to see if the changes we want to introduce are easy to understand. So we built a tool which helps us to see which Pull Requests are available for review so we can trade our PR with other people. Here’s how it looks:
There will be a detailed blog post soon where you’ll be able to read more about this integration, but for now - you can go directly to the repo containing all the stuff you need.
In order to move through the Pull Request lifecycle, we’ve agreed on a few default labels which we use in our projects:
- Ready for Review: as the name says - a Pull Request is ready for others to check, we also use this label to filter out Pull Requests which should appear in our Slack channel when we’re trading Pull Requests in our team,
- Review Done: code review has been done, all of the important comments have been made; from a development perspective - you’re ready to go,
- Ready for QA: QA might go to an integration environment specific to this branch and test everything related to the feature,
- QA Done: all works perfectly, we have a green light from QA,
- No QA: we don’t need QA to test it (most of the time some trivial changes),
- WIP: Work in progress - we want to use the best feature of Pull Request - comments - to talk about the current shape of the code, discuss the next steps, etc.,
- Blocked: some other Pull Request is blocking us - e.g. we need to wait for a green light from the outside world, or some other Pull Request MUST be merged before this one.
Checking the Status of Pull Requests via 3rd Party Integrations
We love the way you can hook up 3rd party integrations to Pull Requests and check many different aspects of the PRs! You can see an example of the status of one of our projects in this image:
Most of the time we use the following integrations:
- CircleCi - as Circle is our choice for Continuous Integration, it’s the most important check here. It tells us if the tests are ok or not - failing specs mean that we definitely don’t want to merge this Pull Request
- Heaven - as mentioned before, we use the Heaven app to build our integration environment for each Pull Request. If the deployment is successful - the “Details” link provides an URL for this environment, if the deployment fails - it shows logs of the unsuccessful build, and we can see what’s wrong
- Code Climate - Code Climate lets us know that we haven’t “harmed” our code with any security issues or that we haven’t worsened the quality of the code (by introducing complicated methods, etc.)
- HoundCI - instead of arguing about line length and which quotes to use (double vs single ones) we have a tool which tells us if our code style is in line with the project’s guidelines. It’s as simple as that, no more time spent on syntax flame wars:)
I hope you found this article useful - we wanted to share our way of using Github and Pull Requests. If you have any questions or suggestions about how we could improve our method even further - don’t hesitate to let us know!
And remember: no tool will solve all code review problems. The key to a great review process is to keep everything clean, short and well explained - reviewing such chunks of changes is much easier and results in a better, higher quality analysis. It’s a lot easier to focus for 10 minutes than to focus for an hour.