Skip to content

Git Flow

Eric Bouchut edited this page Dec 30, 2020 · 145 revisions

Table Of Content

What is git flow?

It is superset of git sub-commands starting with git flow that help automate the above recurrent workflows. With git flow, you type less recurring and error prone boilerplate git commands in order to focus more on what you really need/love to do.

Workflows

Git flow provides 3 git workflows to make the following operations easier and smoother:

Branches

Git flow workflows are based on a set of branches. Two of them, the main branches develop and master will live as long the project itself. The others are called supporting branches. They are short lived branches used to create a feature, release code and provide a hotfix for a bug found in the production code.
Now, let's take a look at each one of them in detail and how they are used for in the git flow branching model.

  • master
    The production ready branch is master.
    This long lived branch is only updated when either or a new release or an urgent bug fix is made available.
    This is not where developers commit code for a new feature nor a bug fix!
  • develop
    It contains the code under development ready to be released when we decide to do so.
    This long lived branch is where branches for feature/release starts off.
    This is not where developers commit code for a new feature nor a bug fix!
  • Feature Branch: feature/XXX
    A short lived feature branch (feature/XXX) is forked-off develop each time you start working on a new feature where XXX can be the name of a ticket (twitter-123), or even better the name of the ticket followed by a super short description of what the feature is about (twitter-123_add_timeline).
    It is intended to contain only the code for this specific feature.
    Once the feature is complete, it is merged into develop to make it available in our shared code base.
    This feature branch then reaches the end of its life and should be removed locally and on the remote.
    No more code must be committed to a feature branch that has been merged or else it will be lost forever.
  • Release Branch: release/A.B.C
    A branch forked-off develop to release the code available in develop at that time. Bugs found when testing the release are fixed on the release branch. When the release is considered complete, it is merged into master and develop. A release tag is added on master.
    The release branch can then be removed because it has reached its end of life.
    Here again, no more code must be committed to a release branch that has been merged or else it will be lost forever.
  • Hotfix Branch: hotfix/A.B.C-n
    A branch forked-off master to fix an urgent bug in production.
    Commits made on the hotfix branch are only intended to fix this bug.
    Once the fix is ready, the branch gets merged back into master and develop. A hotfix tag is also added on master. Then the hotfix branch should be removed locally and from the remote repository.

Naming Convention

Git Flow does not enforce a naming convention for feature, release and hotfix branches, nor even tags.
The names and conventions I use here are only for example purposes. It is up to you to choose the one that floats your boat.
However git flow can be configured to fit your needs. More about this here. Its default configuration uses prefixes to distinguish git flow branches from other branches and tags, that is:

  • release/ is the prefix of a release branch. Say you ask git flow to create the release 1.0.0, when using the default configuration, you then end up with a branch named release/1.0.0.
  • hotfix/ is the prefix of a hotfix branch. Say you ask git flow to create the hotfix 1.0.1, you then end up with a branch named hotfix/1.0.1.

TLDR; When asked, use the default git flow configuration.

Tags are created at the end of a release (1.0.0) and at the end of a hotfix (1.0.1). If you do not use (the default) git flow branch prefixes for releases and hotfixes you may end up with an ambiguity that git will not be able to resolve when you mention 1.0.0 for instance. Does that denotes the release 1.0.0 or the tag 1.0.0 ;-)! You would then need to use refs/tags/1.0.0 to denote the release tag and refs/heads/1.0.0 to denote the release branch. This is a cumbersome issue and this is what these prefixes are aimed to solve. Therefore use them.

Setup

Install

Windows and Linux

https://danielkummer.github.io/git-flow-cheatsheet/#setup

MacOS

brew install git-flow-avh

I prefer installing and using git-flow-avh instead of git-flow because it offers more features, like for instance the --showcommands option useful to see the underlying git commands git-flow is running.

Configure

Git flow needs to be configured locally per git repository.
There is no global configuration which means you need to locally configure each git repository where you want to use git flow.
The configuration settings are stored in your local git config file (.git/config).

https://danielkummer.github.io/git-flow-cheatsheet/#getting_started

# 1) First off, make sure you have both the develop and master branches available locally.
#    If not then run this
git checkout develop
git checkout master

# 2) Configure git flow
git flow init

Using the default values (in between square brackets in the screenshot below) is the recommended way to go except you if you have an existing project with a naming convention for branch(es) that differs from default git flow convention.

FYI, this adds at least the following to the git config file (.git/config).

[gitflow "branch"]
        master = master
        develop = develop
[gitflow "prefix"]
        feature = feature/
        bugfix = bugfix/
        release = release/
        hotfix = hotfix/
        support = support/
        versiontag =

Git flow requires a specific prefix for feature, release and hotfix branches in order to prevent a feature, a release and even a hotfix branch with the same name (suffix) from stepping on each other toes. For instance you can have feature/XXX and release/XXX without any worries because the prefix removes the ambiguity.

Feature

This is how we add a new feature to or fix a non urgent bug in the code base.
Here is a diagram that gives a visual representation of this flow

For an urgent bug in production that requires an immediate fix, use instead the Hotfix workflow.

Start a Feature

A feature branch starts off develop and once finished ends up being merged back into develop.
You don't have to checkout develop beforehand because git flow does this for you (see below).

git flow feature start FEATURE_NAME

Git flow does not have a specific requirement for the name of a feature. A usual naming convention is to use either the ticket of your issue tracker (JIRA, Redmine...) or the ticket followed by a short description of what the feature is about.

Example

  git flow feature start twitter-123_add_timeline
Switched to a new branch 'feature/twitter-123_add_timeline'

Summary of actions:
- A new branch 'feature/twitter-123_add_timeline' was created, based on 'develop'
- You are now on branch 'feature/twitter-123_add_timeline'

Now, start committing on your feature. When done, use:
  git flow feature finish twitter-123_add_timeline

where twitter-123 is the issue/ticket number and add_timeline is the short description. My personal naming convention is to use underscore in between words in the description and in between TICKET and description.

Equivalent Git Commands

git config --local gitflow.branch.feature/twitter-123_add_timeline.base develop
git checkout -b feature/twitter-123_add_timeline develop

Publish a Feature

There are 2 use cases where you need to publish a feature (ie. push the feature branch to the remote repository):

  • multiple developers need to work on this feature
  • you are the only developer committing code on this feature branch, but
    • someone else need to review it before it can be finished
    • you feel more confident having kind of a remote "backup" of the feature branch on the remote repository

Publishing a feature branch consists in pushing it to the remote origin so that the code can be shared with others working on or using this feature.
Once pushed, if it does not exist yet on the remote, the local feature branch is also configured to track its remote counterpart.

git flow feature publish FEATURE_NAME

Example

git flow feature publish twitter-123_add_timeline
* [new branch]      feature/twitter-123_add_timeline -> feature/twitter-123_add_timeline
Branch 'feature/twitter-123_add_timeline' set up to track remote branch 'feature/twitter-123_add_timeline' from 'origin'.
Already on 'feature/twitter-123_add_timeline'
Your branch is up to date with 'origin/feature/twitter-123_add_timeline'.

Summary of actions:
- The remote branch 'feature/twitter-123_add_timeline' was created or updated
- The local branch 'feature/twitter-123_add_timeline' was configured to track the remote branch
- You are now on branch 'feature/twitter-123_add_timeline'

Equivalent Git Commands

# Quietly fetch the remote repository origin
git fetch -q origin

# Push the feature branch to origin and track it
git push -u origin feature/twitter-123_add_timeline:feature/twitter-123_add_timeline
# git push -u origin feature/twitter-123_add_timeline

Get a Published Feature

In order to retrieve locally a feature branch someone else previously started and published, run the below command once.

git flow feature track FEATURE_NAME

Example

git flow feature track twitter-123_add_timeline

Branch 'feature/twitter-123_add_timeline' set up to track remote branch 'feature/twitter-123_add_timeline' from 'origin'.
Switched to a new branch 'feature/twitter-123_add_timeline'

Summary of actions:
- A new remote tracking branch 'feature/twitter-123_add_timeline' was created
- You are now on branch 'feature/twitter-123_add_timeline'

Equivalent Git Commands

git fetch -q origin
git checkout -b feature/twitter-123_add_timeline  origin/feature/twitter-123_add_timeline

Finish a Feature

Once the development of the feature is complete (committed and unit tested), ask git flow to finish it. It will then, on your behalf, merge back the feature branch into develop to make it available both for other developers to use and the next release to embed.

git flow feature finish FEATURE_NAME

where FEATURE_NAME denotes the name of the feature to finish.

Example

git flow feature finish twitter-123_add_timeline
Switched to branch 'develop'
Updating 3a1991b..cef3e34
Fast-forward
...
To github.com:ebouchut/twitter.git
 - [deleted]         feature/twitter-123_add_timeline
Deleted branch feature/twitter-123_add_timeline (was 30da3c8).

Summary of actions:
- The feature branch 'feature/twitter-123_add_timeline' was merged into 'develop'
- Feature branch 'feature/twitter-123_add_timeline' has been locally deleted; it has been remotely deleted from 'origin'
- You are now on branch 'develop'

⚠️ Keep in mind that feature finish does not push develop to the remote repository origin.
You must push develop to origin by yourself after a git flow feature finish.

git push origin develop

Equivalent Git Commands

git fetch -q origin feature/twitter-123_add_timeline
git checkout develop
git merge --ff feature/twitter-123_add_timeline

# Delete remote and local feature branches (some git-flow implementations do not remove the remote feature branch)
git push origin :feature/twitter-123_add_timeline
git branch -d feature/twitter-123_add_timeline

Release

Here is a diagram that gives a visual representation of the flow

[TODO]

Hotfix

We use this process when something went wrong in production and needs to be fixed immediately.

Here is a diagram that gives a visual representation of the flow

Start a Hotfix

A hotfix branch starts off master.
You don't have to checkout master beforehand because git flow does this for you (see below).

git hotfix start A.B.C-n
# You are now on the branch hotfix/A.B.C-n  ready to commit fixes

If the above fails telling you that another hotfix already exists, because you cannot work on 2 hotfixes at the same time. You probably have one old local lingering hotfix branch. You can find out which one with git branch | grep '^hotfix/'. Make sure it has been finished (ie. merged into master and develop) and if so remove it.

git fetch
git branch -r --contains hotfix/A.B.C-n

# If you see `origin/master` and `origin/develop`,
# then you can remove it like so
git branch -d hotfix/A.B.C-n

If the hotfix has not been merged, tell your other self to finish it first or else take the other pill (the blue one) and everything will be fine.

Example

Here is how to start the first hotfix for the release 1.9.4:

git flow hotfix start 1.9.4-1
# You are now on the branch hotfix/1.9.4-1  ready to commit fixes

Equivalent Git Commands

Here is the command git flow runs under the hood to start the hotfix, so you don't have to:

git checkout -b hotfix/1.9.4-1 master

Publish a hotfix

When fixing an urgent bug in production requires several developers to commit code, you need to push the hotfix branch to the remote repository so that others can get it.
Your mileage may vary here, because this command does not exist in all git flow implementations, maybe because pushing a hotfix branch to the remote is not considered a use-case common enough.

git flow hotfix publish A.B.C-n

Example

The first hotfix for the release 1.9.4 is named 1.9.4-1 and the corresponding git branch is hotfix/1.9.4-1. Here is how to push this hotfix branch to the remote origin.

git flow hotfix publish 1.9.4-1

If your git flow implementation does not provide the publish sub-command, then use the below corresponding git command as a workaround.

Equivalent Git Commands

Here are the git command git flow runs under the hood to publish the hotfix, so you don't have to:

git push origin hotfix/1.9.4-1

Get a Published hotfix

There is no dedicated git flow command to retrieve a previously published hotfix branch. The workaround is to fall-back to using regular git commands:

git checkout hotfix/A.B.C-n

Example

git checkout hotfix/1.9.4-1

Finish a Hotfix

You have just finished squashing this bug, which is great. Now let's make the fix available in both master and develop branches.

git hotfix finish A.B.C-n

Git flow runs the following git command under the hood when asked to finish a hotfix:

  • Merge the hotfix branch hotfix/A.B.C-n into master
  • Then, add the tag A.B.C-n on master with the annotation vA.B.C-n
  • Merge the hotfix branch into develop
  • Remove the hotfix branch locally

Example

Here is how to finish the hotfix branch hotfix/1.9.4-1:

git hotfix finish A.B.C-n

Equivalent Git Commands

Here are the git commands, git flow runs under the hood to finish the hotfix, so you don't have to:

git checkout master  
git merge --no-ff hotfix/1.9.4-1
  
git tag -a 1.9.4-1 -m "v1.9.4-1"
  
git checkout develop  
git merge --no-ff hotfix/1.9.4-1
 
git branch -d hotfix/1.9.4-1

Tags

Release candidate tags A.B.C-RCn are added on the release branch.
For instance the RC tag 1.9.4-RC1 is added on the release branch release/1.9.4. RC tags are not part of git flow.

Hotfix tags are added on the master branch
eg. 1.9.4-1 (First hotfix for release v1.9.4)
Git flow adds the tag for you when you finish the hotfix, so you don't have to!

Release tags are added on the master branch
eg. 1.9.4 (release v1.9.4)
Git flow adds the tag for you when you finish a release, so you don't have to!

The table below summarises this.

Type of Tag Added on branch Naming Convention Name Example
Release Candidate Release Branch (release/1.9.4) A.B.C-RCn 1.9.4-RC1
Release master A.B.C 1.9.4
Hotfix master A.B.C-n 1.9.4-1

Sources

Below the sources I used to learn git flow

Thank you Mika and Mhedi for instilling the git flow goodness at LD/S4M.