Git workflow: Manage code complexity
A proper Git workflow procedure for your projects can help you manage a wide range of issues that arise during a project. Learn how to use git as the central focus for your team and why it’s important for your business.
It wasn’t until my first real job at a software company I was exposed to a source control and version system. Since we were a Microsoft shop our source control was a product called Visual SourceSafe. Just about any Microsoft-stack dev my age or older has used it.
As source control systems went, it was terrible. Among the many defects it had:
- data integrity issues, the database site for each repo was capped at 2Gb, files would lose their history or older versions might be purged entirely, preventing you from going backwards to older versions of the project
- exclusive locking, a developer “checked out” a file to be written and they could prevent other developers on the team from modifying the file. why? well this was because
- merging and branching in VSS was a joke, practically non-existent.
- it choked over the network and had trouble supporting even a small team of developers connecting to it
I’m happy to report that most teams now (even Microsoft teams) don’t use SourceSafe. In fact the standard of source control systems now is git.
If you’re unfamiliar with git, it is a free and open distributed version control system. It’s highly efficient and made for lightening fast performance over a variety of networks.
Most freelancers are probably familiar with git because of GitHub, the insanely large repository of open source projects and where everyone seems to distribute open source projects now (poor SourceForge).
There are a bunch of articles to help you get started with learning git and they do a much better job of teaching you how to commit, push, branch and merge. What I want to discuss is how we use git to manage our projects and specifically the workflow strategy we employ to keep things in sync.
Our git workflow process is a simplified model of GitFlow. Basically we have the following branches in all of our projects.
- feature branches
- hot fixes
The master branch contains code that is live and operating on production. This branch can only be merged with the ‘dev’ and ‘hotfix’ branches. We never commit a feature or change to this branch directly. Everything is a merge from either ‘dev’ or a hot fix branch.
The dev branch is branched off from master. This branch reflects what’s currently on our stage or testing server. Once a developer has completed their work in a feature or hot fix branch I’ll merge into ‘dev’ and then push the code to our staging environment.
Feature branches are branched off from dev and can only be merged back into dev. They can be named anything really as long as they’re separate from “master” and “dev.” Each developer before they work on a feature will create a feature branch and commit their changes to this branch as they develop. I like to have feature branches pushed to ‘origin’ just because I may need to check our team’s work or help out with an issue remotely.
Here’s an example of a feature branch in SourceTree (a free git client). The yellow branch is ‘feature/updated-nav’ and you can see the line showing it came from the ‘dev’ branch (in purple).
At times during development of new features there might be issues the client has reported from production that require fixing. Handling of these cases is important. We don’t want to create a feature branch off of dev because that’s still in active development and the branch would contain code that’s not yet ready for production.
The solution is a hotfix branch. It branches off of master and is merged into both ‘dev’ and ‘master.’ Once we have a fix committed, we merge with ‘dev’ for testing. Once the issue has been resolved we then merge the hot fix branch into ‘master.’
For the hot fix branch to work, any fixes or tweaks to the code while testing on ‘dev’ must be applied to the hot fix branch so they can be merged with ‘master.’ It’s a bit tricky but once you get used to it managing maintenance items while working on a large feature is much easier to control.
These branches aren’t typically in my configuration, but from time to time I break them out to help with difficult management tasks.
These are called “Release Branches” in the GitFlow docs, but there are a few differences in my git workflow approach. I reserve integration branches if there are large features (or multiple features) that need to be tested and integrated before they’re ready for ‘dev’. Merges can be complex and there have been numerous times where two feature branches have conflicted which makes it impossible to deploy to customer testing until it’s resolved. When I use these branches, I take it off the latest copy of dev and then separately merge whatever feature branches I need to. After some internal testing and making sure all the conflicts are resolved, I merge back into ‘dev’.
This is a new branch type I came up with for a client. They had an internal team member working an a large mobile responsive release at the same time we were working on a large feature update.
Unfortunately the responsive work (after testing on an integration branch) was just too unstable for integrating back into dev. I needed someway for the client to have a second staging environment for just the mobile responsive work. I created a separate branch that auto deployed to a special ‘alpha’ test environment, This allowed the client and their internal dev to work independently of us until they were ready to merge back into ‘dev’ and do a more formal round of testing.
This is the general process we use to manage the code for our software projects using our git workflow. The biggest thing I want to stress is to not be afraid of branching and merging. Using only a single ‘master’ branch may seem easier, but as projects get bigger it can often make your life harder. Fully learning git and figuring out a branching strategy is important to successfully managing a living, breathing client codebase.
There are a few great articles online that can help you figure out a git workflow for your projects.
A successful Git branching model