Implementing the 'Git flow'
How we use 'git flow' in one of our projects
8 min read
8 min read
Git can be used in a variety of ways which is cool. But still, when working within a team, it is good to have a consensus on a common, shared approach in order to avoid conflicts. This article quickly explains how we implemented the “git flow” pattern in one of our projects.
…is a popular strategy which works around the master branch, but in a less “aggressive” way (than the GitHub flow pattern for instance). You have two main branches:
master branch contains the latest production code that has been deployed, and versioned with appropriate tags for each release.
develop branch that gets branched off master and contains the latest code for the next feature that is being developed. For each new feature there might be lots of feature branches (always branched off the “develop” branch).
Beside the main branches, there are so-called supporting branches:
Beside those, there are supporting branches:
feature branches contain the development state for a single feature of the overall product (i.e. a user story). They are merged off the
hotfix branches are branches for quick and severe bugfixes. they are usually branched off the master branch, fixed in the hotfix branch and then merged back in master and develop as well.
release branch is a branch for preparing the next release. No new features will be developed on this branch but rather it contains some last fixes (also bugfixes) and adjustments for going into production.
Many people prefer to see
master as their development branch and instead have a dedicated one for the production environment.
Such a production oriented branching strategy has
Supporting branches are:
In my opinion tools are great as they (mostly) give you some productivity boost. Nevetheless you should always understand what they do behind the scenes. This section lists the commands you’ll need to manually implement the production-oriented “git flow” pattern shown above.
First of all you have to initialize an empty repository and eventually connect it immediately to your remote one. Obviously, feel free to skip this step if you already have one.
$ git init $ git remote add origin [email protected]
Furthermore I’d suggest to also add a
.gitignore file. You may start from an existing one based on your project type: Github .gitignore repository.
“push” everything up to your remote repo.
$ git push --set-upstream origin master
$ git pull $ git checkout -b userstory/login
Do some commits and then publish the feature on the remote repo (if not a tiny one of a couple of hours)
$ git push origin userstory/login
Frequently update from origin/master to get the latest changes that have been pushed to the repo by your peers.
$ git fetch origin master $ git rebase origin/master
Alternatively checkout your master branch and execute
$ git pull master $ git checkout <yourfeaturebranch> $ git rebase master
Note, when you rebase with master, your branch might not be easily updateable with its remote counterpart (given you synched it up to a central repo). In such case you can use the
Caution! Inform yourself on the Git docs about the potential dangerous side effects when using the
Only use the force flag if you haven’t shared the branch with anyone and it is simply your central backup. Force overwrites the history with your local repository state inside your current branch.
$ git push --force origin <yourfeaturebranch>
Before merging back to master, make sure you polish your git history. This is something I see people often forget or don't care about. But it's really easy and leads to a much clearer and more understandable history (which helps in resolving issues as well). In this article I explain how do to it.
Merge it back into master
$ git checkout master $ git pull $ git merge --no-ff userstory/login
--no-ff means no fast-forward to keep track from where certain changes have originated.
In order to not forget the
--no-ff flag you might want to configure it as the default behavior when merging into master by executing the following command:
git config branch.master.mergeoptions "--no-ff"
In case of conflicts, resolve them and then push the master
$ git push
and remove the userstory (locally and remote)
$ git branch -d userstory/login $ git push origin :userstory/login
$ git checkout -b release/0.1.0
$ git checkout production $ git pull $ git merge --no-ff release/0.1.0 $ git tag v0.1.0 $ git push --tags origin production
$ git checkout production $ git checkout -b hotfix/login-does-not-work
After testing it, merge back into production
$ git checkout production $ git merge --no-ff hotfix/login-does-not-work $ git tag v0.1.1 $ git push --tags
Obviously also merge those changes back to master as well
$ git checkout master $ git merge --no-ff hotfix/login-does-not-work
And then delete the hotfix branch
$ git branch -d hotfix/login-does-not-work
Git Flow is a git command line extension to facilitate the usage of the “git flow” pattern.
So, if you mastered to use the git flow pattern manually, you’re ready to go with it.
To install them, simply copy&paste the aliases into your
.gitconfig file. You should find it in your user profile directory (
~ on unix systems;
C:\users\<yourname>\ on Windows).
Please refer to my recent blog post “Git flow with Jenkins and GitLab” for further details on how to configure your build environment.
We adopted the git flow pattern in one of our projects with a team getting in touch with git for the first time (they used TFS before). I introduced them to the Git basics and then they started straight ahead and surprisingly the switch was really easy. By using git flow we minimized the conflicting merges and thus potential problems in the development flow.
So how did we use it? The team applied some kind of Scrum (we’re new to it, thus “some kind of” :)). We have two weeks iterations with an initial planning phase (usually on thursday morning) and we have the tester on the team (yay!).
task/<trello-card-#>-titlefor tasks and
masteror creates a merge request on GitLab assigned to another developer for code reviewing. When
mastergets pushed to GitLab, Jenkins automatically takes it and publishes it to our dev server instance.
masterbranch gets automatically published to our test server instance s.t. the tester in our team can continue to test the implemented stories and either mark them as done or reject them within our spring cycle. Furthermore a series of automated jMeter tests get executed that verify the correct functioning of our REST api as well as the performance of our endpoints.
production. This is automatically detected by Jenkins which - again - publishes to our preproduction server instance which is also accessible by our customer.
We do not use release branches as we don’t need them so far. There is no preparatory work to be done, although that might eventually change in the future.
That’s the flow we came up with after a few iterations and dicussions within the team and with our tester. What’s your approach?? I’d be interested to hear in the comments.