Git Flow vs Feature Branches

Recently, on a project using git flow, I ran into a situation where a merge conflict resulted in a yak shave/lost time.

Essentially - someone committed directly to master. When trying to run git flow feature finish the script died due to a conflict. This:

  • left uncommitted changes on master
  • left a floating release branch that needed to be manually deleted
  • required a conflict resolution commit that needed to be merged back to develop
  • required the original commits on master to be merged back onto develop

This was a lot of lost time and confusion to resolve what was a simple mistake (someone committing to master)

This raises the question - what benefit is there to git flow. My preferred git strategy is simple feature branches (and continuous delivery) like so:

  • master is always production ready
  • all other work is done on a feature (aka topic) branch. This includes new features and hot fixes

That’s it. It’s a simple strategy that covers all potential use cases for most web apps.

Here are some related structural and delivery concepts:

  • continuous integration should run all branches. (Travis ci, badges, and github work well here)
  • pull requests should be used to merge code into master. Reviewing pull requests is great for knowledge sharing and code discussions.
  • master should get pushed to production after a pull request is merged
  • if one bit of work depends on another bit of work then they are done on the same branch (this may speak to poorly broken down features)

This strategy can do everything that git flow can do, but has the benefits of: less overhead, smaller deploys (should only ever be one be feature at a time)

for virtually all web apps - this seems like a superior strategy to git flow. In my mind - git flow only has benefits for large release cycles (eg desktop type products with specify version numbers)

@justin, @martin or anyone else that is a fan of git flow - can you specify any situation that git flow handles better than the strategy above?

@geoffevason, I like this simple branching strategy as well. That is what I have used most often in the past, sometimes even just working off of master, i.e continuous delivery. However this type of development requires you to have a very solid automated test suite with continuous integration to get rapid feedback. Otherwise you’ll be testing in production.

I can see the benefit of having an additional development branch in some projects where for example there is poor code coverage. This way you can do all your testing on development (automated and/or manual) and only merge to master when you feel confident that the code is production ready.

The main benefit of git-flow is when you want an extra level before you push to production. You have a branch that you can be sure has a number of features integrated and do good testing on it.

Another situation that comes up is when you need to quickly make a small change to production (master). The git-flow hot-fix concept works great for that.

@geoffevason, I’d be interested to see if you think the changes that I’ve suggested would have avoided the problem you just saw. These steps boil down to:

  1. Moving to the git-flow-avh brew formula
  2. Using my updated scripts

@justin - the hot-fix concept isn’t a benefit of git flow - since it works just that same in the feature branch strategy. In both cases you just have to merge a bug fix branch into master.

Regarding ‘an extra level before you push to production’ - this may be true - but why would you ever want that? The only thing I can think of is if you’re using a train release model. That model doesn’t really belong in the web app world. Can you tell me any other time you might want an extra step? @martin suggested that you might want this when you have poor test coverage - so that you want to batch test a bunch of changes before deploying to production. I have some issues with this argument as well.

First and foremost, it’s solving the wrong problem. Adding more branches because you’re worried about introducing bugs is like not driving your car on the highway because your seat-belts don’t work. The right solution is clearly just to get your seat-belts fixed.

Second, to actually catch bugs before production, you need to do QA before you deploy. This is true regardless of how you branch. If you don’t do proper QA - you’re just more likely to introduce a bug with any given deploy, and you’re making it harder to find since the deploys will be bigger. If you do do QA - it’s debatable whether batching the QA is more efficient or not.

So while I agree that git flow does work for adding an extra step before production - I still can’t think of a valid reason to do this in the web world.

I had an interesting discussion with @geoffevason. I think the crux of the matter comes down to either:

  1. The non-git-flow model where ALL development work that is to be reviewed is done on a feature branch, and once reviewed, that work goes into the master branch, which is then immediately run through CI and then deployed.

  2. The git-flow model where bigger features are done on feature branches, and small code changes can be done on the develop branch.

The problem with #1 is that there are often features that partially dependent on each other, and the develop branch gives you a nice place to get everything merged and tested before going to master.

Some will suggest just using a different tag for what’s deployed on master. I definitely prefer having a develop branch over that model.

@justin, I think you summarized it well. My take is that there is no right or wrong approach here. It really depends on the type of project you are working on. If the team members find themselves integrating their work frequently and need a “staging” environment to flush out the bugs then #2 seems like a better fit. Otherwise I agree with @geoffevason that it can become an overkill. Also note that with #1 nothing prevents you from creating a temporary remote staging or development branch to integrate code from several feature branches - and then remove it when everything is merged into master.

I don’t use dedicated ‘dev’ branch anymore. If 2+ feature branches need to be merged before going into master I’ll create a new branch just for the merging and then merge into master.

I also have started to use feature flags more. This way if a feature branch is “finished” but still depends on other feature branches being developed it can still be merged into master but be “turned off” inside of the app. The means we now merge into master a lot more and causes a lot less problems keeping everything in sync.

and with the git-flow scripts, I find it easier that doing all the branching stuff separately…but the hazard with the git-flow scripts is when git novices use them, and don’t understand what the shortcuts are doing…