Workflows with git-flow
When using version control in a team, it's crucial to agree on a workflow. Git in particular allows to do lots of things in lots of ways. However, if you don't use a common workflow in your team, confusion is inevitable.
In principle, you're free to define your workflow of choice just as you want it - or you simply adopt an existing one.
In this chapter, we'll look at a workflow that has become quite popular in recent years: "git-flow".
What is git-flow?
By installing git-flow, you'll have a handful of extra commands available. Each of these commands performs multiple tasks automatically and in a predefined order. And voila - there we have our workflows!
git-flow is by no means a replacement for Git. It's just a set of scripts that combine standard Git commands in a clever way.
Strictly speaking, you wouldn't even have to install anything to use the git-flow workflows: you could easily learn which workflow involves which individual tasks - and simply perform these Git commands (with the right parameters and in the right order) on your own. The git-flow scripts, however, save you from having to memorize all of this.
A couple of different forks of git-flow have emerged in recent years. In this chapter, we're using one of the most popular ones: the AVH Edition.
For details on how to install git-flow, please have a look at the official documentation.
Setting Up git-flow in a Project
When you "switch on" git-flow in a project, Git still works the same way in this repository. It is totally up to you to use special git-flow commands and normal Git commands in this repository side by side. Put another way, git-flow doesn't alter your repository in any dramatic way.
That being said, however, git-flow indeed expects some conventions. Let's initialize it in a new project and we'll instantly see:
$ git flow init Initialized empty Git repository in /Users/tobi/acme-website/.git/ Branch name for production releases: [master] Branch name for "next release" development: [develop] How to name your supporting branch prefixes? Feature branches? [feature/] Release branches? [release/] Hotfix branches? [hotfix/]
When calling "git flow init" in the base folder of a project (no matter if it already contains an existing Git repository or not), an interactive setup assistant guides you through the initialization. This sounds a bit pompuous... because actually, it's just about configuring some naming conventions for your branches.
Although the setup assistant allows you to enter any names you like, I strongly suggest you stick with the default naming scheme and simply confirm each step.
The git-flow model expects two main branches in a repository:
- master always and exclusively contains production code. You don't work directly on the master branch but instead in designated, separate feature branches (which we'll talk about in a minute). Not committing directly to the master branch is a common hygiene rule in many workflows.
- develop is the basis for any new development efforts you make: when you start a new feature branch it will be based on develop. Additionally, this branch also aggregates any finished features, waiting to be integrated and deployed via master.
These two branches are so-called long-running branches: they remain in your project during its whole lifetime. Other branches, e.g. for features or releases, only exist temporarily: they are created on demand and are deleted after they've fulfilled their purpose.
Let's start exploring all of this in some real-world use cases.
Working on a feature is by far the most common task for any developer. That's why git-flow offers a couple of workflows around feature development that help do this in an organized way.
Starting a New Feature
Let's start working on a new "rss-feed" feature:
$ git flow feature start rss-feed Switched to a new branch 'feature/rss-feed' Summary of actions: - A new branch 'feature/rss-feed' was created, based on 'develop' - You are now on branch 'feature/rss-feed'
At the end of each command's output, git-flow adds a (very helpful) description of what it just did.
When you need help about a command up front you can always request help, e.g.:
$ git flow feature help
By starting a feature like this, git-flow created a new branch called "feature/rss-feed" (the "feature/" prefix was one of the configurable options on setup). As you already know, using separate branches for your feature development is one of the most important ground rules in version control.
git-flow also directly checks out the new branch so you can jump right into work.
Finishing a Feature
After some time of hard work and a number of clever commits, our feature is finally done:
$ git flow feature finish rss-feed Switched to branch 'develop' Updating 6bcf266..41748ad Fast-forward feed.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feed.xml Deleted branch feature/rss-feed (was 41748ad).
Most importantly, the "feature finish" command integrates our work back into the main "develop" branch. There, it waits...
- ...to be thoroughly tested in the broader "develop" context.
- ...to be released at a later time with all the other features that accumulate in the "develop" branch.
git-flow also cleans up after us: it deletes the (now obsolete) feature branch and checks out the "develop" branch.
Release management is another important topic that version control deals with. Let's look at how to create and publish releases with git-flow.
Creating a New Release
Do you feel that your current code on the "develop" branch is ripe for a new release? This should mean that it (a) contains all the new features and fixes and (b) has been thoroughly tested. If both (a) and (b) are true, you're ready to start a new release:
$ git flow release start 1.1.5 Switched to a new branch 'release/1.1.5'
Note that release branches are named using version numbers. In addition to being an obvious choice, this naming scheme has a a nice side-effect: git-flow can automatically tag the release commit appropriately when we later finish the release.
With a new release branch in place, popular last preparations include bumping the version number (if your type of project keeps note of the version number somewhere in a file) and making any last-minute adaptions.
Finishing the Release
It's time to hit the red danger button and finish our release:
git flow release finish 1.1.5
This triggers a couple of actions:
- First, git-flow pulls from the remote repository to make sure you are up-to-date.
- Then, the release content is merged back into both "master" and "develop" (so that not only the production code is up-to-date, but also new feature branches will be based off the latest code).
- To easily identify and reference it later, the release commit is tagged with the release's name ("1.1.5" in our case).
- To clean up, the release branch is deleted and we're back on "develop".
From Git's point of view, the release is now finished. Depending on your setup, committing on "master" might have already triggered your deployment process - or you now manually do anything necessary to get your software product into the hands of your users.
As thoroughly tested as your releases might be: all too often, just a couple of hours or days later, a little bug might nonetheless show its antennas. For cases like these, git-flow offers the special "hotfix" workflow (since neither a "feature" branch nor a "release" branch would be appropriate).
$ git flow hotfix start missing-link
This creates a new branch named "hotfix/missing-link". Since we need to fix production code, the hotfix branch is based off of "master".
This is also the most obvious distinction from release branches, which are based off of the "develop" branch. Because you wouldn't want to base a production hotfix on your (still unstable) develop code...
Just like with a release, however, we bump up our project's version number and - of course - fix that bug!
With our solution committed to the hotfix branch, it's time to wrap up:
$ git flow hotfix finish missing-link
The procedure is very similar to finishing a release:
- The changes are merged both into "master" as well as into "develop" (to make sure the bug doesn't slip into the next release, again).
- The hotfix is tagged for easy reference.
- The branch is deleted and "develop" is checked out again.
As with a release, now's the time to build / deploy your product (in case this hasn't already been triggered automatically).
Workflows: A Recap
Let me finish this chapter by stressing an important point once more: git-flow doesn't add any functionality on top of Git. It's simply a set of scripts that bundle Git commands into workflows.
However, agreeing on a fixed process makes collaborating in a team much easier: everybody, from the "Git pro" to the "version control newbie", knows how certain tasks ought to be done.
Keep in mind, though, that you don't have to use git-flow to achieve this: often, after some time and experience, teams notice that they don't need git-flow anymore. Once the basic parts and goals of a workflow are understood, you're free to define your own.