Like a lot of developers my first introduction to version control was through Git. Of course, back then, Git and GitHub, the Git hosting site were one and the same to me. I followed the setup instructions when I first signed up and created and cloned my first repositories. I didn’t know why I should be using Git or version control at all until much later but I did it anyway because that’s what all the “good” developers were doing. GitHub is a blessing and curse for version control. It sets us up for proper versioning of our projects but it also teaches us some bad habits. One thing GitHub fails to teach us about it how and why it’s important to have set guidelines for branching on your project, even if you’re the only developer. Let’s talk about why it’s important and a popular, useful branching strategy anyone can use for their project.
I happen to be lead developer on a number of open source projects, some of which people actually use! Right now, I have two important projects that I can use as examples for the why and how of this lesson on branching strategies: Fraction.less Boilerplate and MoonWeather, my new iOS app. One of these is open source and the other is one that I’m the only developer for. Both need a proper branching strategy for success.
Why is it important?
When we first pick up Git, a lot of us think that the Origin remote and the Master branch is all we have available to us and that additional remotes and branches are for those super advanced users. Not so. These are actually the very basics of Git and not using these features defeats a lot of the purpose of using version control. If you’re not taking advantage of remotes and branching you might as well just use a Time Machine backup of your hard drive as your VCS.
You need more than one remote
In Git a remote is a copy of your repository stored somewhere other than your local system. Remotes are where you’d clone fresh copies of your projects from.
Remotes in Open Source Projects
For Fraction.less I have the origin remote and the backup remote. For an open source project like this one, the Origin is GitHub. All the code and branches that I want the public to have access to is in the Origin remote. My Backup remote is hosted on my own server. It’s incredibly simple to host your own Git repositories and I’ve argued many times before that you don’t need to host everything on GitHub – you should host your own Git repos. The Backup remote is for code I don’t want released to the public for one reason or another. It may be liable to break someone’s site, it might have private information in it, who knows. More importantly, I use the Backup remote for times when GitHub is down and just for peace of mind. GitHub has gone down in the past and I have to laugh when everyone starts whining that they can’t work with Git until it comes back online. Umm, guys, you should have a self-hosted remote that you and your team can work from until GitHub comes back online.
Remotes in Closed Source Projects
For a private project like MoonWeather I host an Origin, Staging, and Deploy remote. In this case each remote has a different purpose and only the Origin is for true version control. Staging is the remote that receives only commits from the testing branch and copies the new code to the staging server for live testing. Once that’s finished we merge our changes over to the master branch and push to our Origin and our Deploy remotes. The Origin just saves the current, stable release of the project while the Deploy remote deploys the code into production for all app users to use.
A solid branching strategy
Branching is important to your ability to separate stable code from in-progress or broken code. When your project is small like all of ours are at some point branches don’t really matter all that much. But once you have that first stable version of your project and it’s live on the web you had better set up a solid branching system or I guarantee you that broken code will end up in public by accident, pissing off a lot of people.
I use this strategy for my open source and private projects. The reasoning for it is slightly different in each but the concepts are the same. I use three main branches: master, develop, and *-feature branches. That’s all you really need.
The Develop Branch
We’re starting with the Develop branch because everything revolves around it. When you first create a Git repository you should immediately run
git checkout -b develop to create this new branch. The Develop branch is where the bulk of your work will take place. For version 1 of your project you’ll develop in this branch until it’s stable. Once it’s ready and has been tested and verified as stable you merge this branch into the Master branch. You never code in Master, you only merge changes from Develop into it. After you reach version 1 there’s a risk of the Develop branch becoming messy. At that point you’ll need to cut Feature branches that will feed into the Develop branch. When Feature branches are merged into Develop and have been tested its time to merge them back into Master. If a Feature branch causes bugs in Develop, you fix them first then merge them into Master. Some go a step further and actually cut a pre-release branch off of Develop whenever a new feature is merged into it and then only merge that branch into Master. For larger projects this makes sense but for our purposes I don’t want to complicate this so I’m only mentioning it for completeness.
The Master Branch
Your master branch is what Git drops you into by default. In our branching strategy we don’t use the master branch much at all. In fact it is strictly forbidden to work in the master branch!
The master branch is for stable, production-ready code only. You’ll fix bugs in the Develop branch, add new major features in Feature branches, and experiment in any number of separate smaller branches if needed.
Feature branches are numerous in my projects. Once a working alpha or beta version of the project is finished I start cutting Feature branches so that what I’ve already got working is not tainted by my experimentation. Each new feature should get it’s own branch so that it’s development does not interfere with the rest of the project or other new features being developed at the same time. Once a feature is ready, it is merged into our Develop branch, tested, fixed if necessary, then Develop gets merged into Master.
Branching in Open Source Projects
Branching in open source projects is important because of the number of commiters that could potentially be pushing and pulling code to your project. It’s easy to introduce bugs when you’re merging in commits from multiple commiters. In open source projects it’s usually a good idea to tell contributors to make the smallest changes possible in their pull requests. You’d then pull their work into a brand new feature branch. As the project maintainer you’ll want to test the contributor’s code so you create a new Feature branch off of Develop regardless of whether the contributor wants to fix a bug found in Master or add to a new feature.
Branching in Closed Source Projects
I use the same exact strategy implemented in my own personal, private repositories. I don’t have contributors but I do have users and many of them are paying me. A proper branching strategy can save you from unhappy customers. Let’s take MoonWeather as an example. MoonWeather is my first iOS app and the first project which I’m charging real money for. MoonWeather relies on an API I built to work properly. If my API goes down then I end up losing business. There have been many times that I broke my own API while fixing bugs and adding new features. Thankfully I was using the branching strategy I describe here. Another question is what happens as the API grows and different users have different versions of the iOS app. If each version relies on a different version of the API then I need to make source control a priority. I can’t expect to release a new version of MoonWeather for iOS that uses a new version of the API that older versions don’t support and not make people angry. A final, and quite scary consideration is what happens when (not if) my server blows up? Servers blow up and it happens to everyone at one point or anoher. If I only had a single remote with a single branch I may not ever be able to get my API online again.
Let’s say I had a backup remote but only a single Master branch for MoonWeather’s API and the server it runs on just blew up. Now what? Well, I could just deploy the API again on another server, right? You’d think so but the last version that was deployed was about 50 commits ago and I’m not using a proper branching strategy. Nor am I tagging my code as I release it. All I have to go off of are my commits which aren’t very descriptive. If there was no backup remote then I’d be truly fucked. But with remotes that mirror each other and a proper branching strategy my app is safe and sound from most disasters.
So please, take the time to learn more about Git beyond what the GitHub intro docs tell you. Here are some great places to start:
- Git Branching Workflows – Goes over pretty much what I talked about here
- Working with Remotes – All about setting up remotes. I know GitHub shows you a pretty web page but it’s really not necessary to work with Git at all.
- Remote Branches – Great for understanding the difference between the repo on your computer and why having remotes is so important