Here at BizStream, we’ve been using GitFlow for a while now and as we hit pain points we’ve really seen the wisdom of running with GitFlow standards. We like them, however, they are rather vague as they can apply to a whole lot of development (desktop, mobile, web, IoT, etc...). The normal GitFlow setup has two persistent branches, Master and Develop. It also has three types of temporary branches Hotfixes, Releases and Features. We’ll go through each of these to see how and why each type of branch is used.
Feature branches represent stories or cards on the sprint. If you’re using Jira, Mavenlink, Trello or whatever various project management tools your project manager wants to try this week, you’re probably going to have features (or cards, or tasks, or whatever). Features represent a self-contained chunk of work that needs to be done. Feature Branches are the space where you do that work.
Feature Branches begin by branching from Develop to a new local branch. Here a developer can work in isolation on a Story. The dev environment is normally your local machine. However, in terms of Kentico
usage, pulling a full instance down and getting it hosted locally to keep each developers machine synced is really more effort than it’s worth. Our normal mode of operation is to connect to a shared development instance while developing. There has been a whole lot written against the shared database model. However, we’re sharing a CMS with an API vs sharing a database directly and that insulates us from the dangers of shared database enough to make it worth the trade-off.
A Feature can be completed only when it passes all acceptance criteria (and all acceptance criteria are signed off on), all content is fully prepared, and all of the latest Develop Branch changes have been merged in. When you consider a feature complete, make a pull request and have another developer check your work. For the developer working on the feature, it will be important to test that any work completed in dev didn't break your work during the merge. For technical leads (and other people reviewing pull requests), it's important to really dig into the merge points and make sure that a pull request isn’t creating conflicts in another developers code. Once signed off on that feature can get merged into production.
Develop represents the first line of defense against, “Works on my machine”. You should be running with an auto-build process be it TeamCity, VSTS, Jenkins or something similar. Anything that gets merged into Develop should get auto-built. A very important step of this process should be taking the time to verify that the auto-build process deployed your changes correctly and didn’t break the build. If you did break the build or even just made make a mistake during the merge it's OK to make small commits directly to Develop to get the build running again (but not feature fixes!). Once you have certified that your feature has been merged and all the acceptance criteria pass, it's important to go back and prune your feature branch relatively quickly, while the feature is still fresh in your mind.
This ideally is more than just a deleting a branch, it’s the point in your features development where you put on the detail-oriented finishing touches. Document all your deployment dependencies/steps, make sure the test plan looks good for QA, update any documentation that needs it, or maybe take the time to write up some notes for the client. It’s not all on the developer, this is when your Team Lead/PM/QA should kick a task back if you don’t have the above items documented. Make doubly sure that all PageTypes, LocalizationStrings, CustomModules, API keys are clearly documented on the task or better on a dedicated deployment task at this point. When QA signs off on Develop we are clear to merge to User Acceptance Testing (UAT).
Release (auto-build and transient)
The current Release represents the current working state of your UAT environment and all the features that will be going out at the end of the sprint. Once a Feature Branch is truly confirmed as working in Develop we want to simulate an actual production release. That’s where our Release Branches really shine. Deployments are often more than just pushing straight code. Devs have content to move, localization needs to happen, memberships need to be updated, APIs need to be flexed, etc. There’s a lot that can go wrong during a production push that has nothing to do with bugs in code and you want to have the ability to catch things here.
Another vitally important piece is client sign off on Features in a stable environment. In many situations, UAT is where content goes to be created. Developers can create the framework for your website however, you’ll also need the services of sales, translators, content creators, artists, and a whole host of other marketing work completed before a deployment. If UAT isn’t solid, this work can grind to a halt. Making sure that you keep your release branch as clean as possible is vitally important. Also important, is the ability to roll back to a previous commit on the Release Branch if and when things do go south, not even just due to code issues.
When we push from Develop to UAT we should really be taking notes and monitoring site performance. Take note of what content you can stage ahead of a push, how the site behaves when it’s updated, and what you need to do to ensure a positive user experience. Really go to town here and treat this like a practice run for your end of sprint prod deployment. Ideally, you should be merging from Develop to release as early and often as possible; building confidence in your ability to deploy to production when that final push comes.
We normally create one Release Branch named after the sprint right before every sprint kickoff and yes, this does often require going into your build and updating Jenkins/TeamCity once a sprint. If you’re wondering what the need for all of this is, keep this scenario in mind; It's getting towards the end of a sprint and your feature isn't going to make it. Maybe content isn’t ready, or a bug is found in a critical piece of infrastructure, for whatever reason you’ll have to punt this to the next sprint. You could leave the code in the Feature Branch, however, on fast-paced projects, the code you’re not actively working on can quickly fall behind the head version on Develop and rot. Let your team lead (or whoever is in charge of the project) know and they'll start the next sprint’s Release Branch. This is where you can merge your code. Now, as soon as the current sprint hits production your code will be ready to go. Also, a pretty common request is for a code freeze while final QA is happening at the end of a sprint. However, the dev train has no brakes. Keep your team rolling forward by starting the next release early ASAP.
When a release is close to going out, you should try to pull the entire team together to create a demo for the stakeholders. If demo magic happens and something doesn't work, the dev team may need to make small bug fix commits, which may be made directly to the Release Branch. Once a release is fully certified for deployment in UAT, any last second fixes will be merged back to Develop before the entire branch is merged into Master. My general rule of thumb for pruning Release Branches is that I like to keep at most 3 around (last, current, and next).
Master (push button build)
Master represents the current working state of production. No one should ever touch Master directly for any reason, only merges from Release Branches and hotfixes are allowed. When a deployment to production happens you should have a plan and ensure it’s followed every time you pushed from Develop. This is why it is very important to document all items that need to be synced while deploying from dev to UAT. Every time a deployment to production happens the entire team should spend some time in production certifying that their changes were pushed correctly.
Bugs in production happen. When something is on fire right now, you need a Hotfix. Hotfixes begin life by branching from Master and should be used for very quick band-aid fixes. If possible, you should merge your hotfix into the last deployed release branch to test in UAT. However, depending on the severity, merging it directly to Master may be the best course of action. Hotfixes should either merge directly back into the current Develop branch or at least generate a new Feature to make sure that the fix doesn't get lost.
So that’s the general break down of how GitFlow gets you from Feature to Production. The process is generally pretty standardized but every company, or project within the company, may end up modifying it in one way or another. At BizStream we have the privilege of working with many variations of GitFlow so if you have any questions chances are someone here has seen it. Feel free to reach out!