Question

I am thinking of extending the git-flow model for my current workplace, due to a particular scenario. But my scenario is so common that I'm surprised no-one's done this before with the git-flow model, and this makes me think I've missed an obvious problem. My question is: Is my proposed extension flawed?

The scenario: I have a number of development teams who develop from a common codebase, and we push out releases through several (permanent) environments: first to the systems integration environment (SIT), then to the UAT environment, then to pre-prod, and finally to production. This is strictly sequential, although any release candidate may fail in any environment, and so not make it any further. Thus each later environment is simply a slower-moving version of the previous environment.

We are introducing git for source control, we need a workflow, and git-flow looks like a good start.

We asked ourselves how to capture (i.e. how to know) what's in each environment at any time. The git-flow model seems to have essentially two core states: master and develop. They have an "infinite lifespan". Other branches are just "supporting branches" with a "limited life time". They exist only to allow development and to go from development to production (via a temporary release state). The git-flow model is based around going from development to release.

However, this doesn't map logically onto our scenario, with its multi-stage release sequence. I'm fine with the develop branch, of course. And the master branch clearly does map to our production environment. The original git-flow description says this about master:

Therefore, each time when changes are merged back into master, this is a new production release by definition. We tend to be very strict at this, so that theoretically, we could use a Git hook script to automatically build and roll-out our software to our production servers everytime there was a commit on master.

Since master is a continuous record of production, it seems consistent that we should extend the git-flow model to have corresponding branches for SIT, UAT, and pre-prod. After all, they are permanent environments, with strict release procedures. They just change a bit quicker than production.

These additional, permanent, branches sit between develop and master, just as their corresponding environments do.

This now means it's easy to track releases to each environment, and the state of each environment. And merges for each are easier, too: the SIT branch requires a merge from develop, the UAT branch requires a merge from the SIT branch, the pre-prod branch requires a merge from the UAT branch, and finally the master branch (for production) requires a merge from the pre-prod branch. Each later branch is simply a slower-moving version of the previous branch.

Have I missed something?

Was it helpful?

Solution

There is no reason I can see to adapt the flow against your model. You say you work sequentially SIT -> UAT -> Pre-Prod. Perfect. Once develop is stable (i.e. all features due for release are feature-finish[ed]) then do release start and move this to your SIT platform for QA. Once the release start has taken place, development can continue on the develop branch. master stays static until the release is completed.

Once QA is satisfied then the release branch gets moved to UAT. UAT passes and the code rolled to live and you carry out release finish to merge back to master / develop.

master should always be a reflection of what is currently on the live platform whilst develop is a reflection of code under active development. release branches contain a static cut of develop against which bug fixes are applied (no new features ever get pushed into this branch or you're not using git-flow).

Based on your description I'd be inclined to say you have mis-understood the git-flow model because from what I can see it fits perfectly into the scenario you describe, all you need to care about during SIT -> UAT -> Pre-Prod is the release branch, "forget" master / develop even exist at this stage.

Response to comments

Since I first posted this answer there have been a number of comments which have raised questions about how the model works in a number of different scenarios.

  1. Client has requested improvements to existing features

Answer:

DO NOT (I cannot stress this strongly enough) allow new features / enhancements to be added to the release branch. This is scope creep. New features are new work. They need to be costed for separately and must be treated separately. Whether your client is your own company or a 3rd party, the one thing they understand is cost. Point out to them that if they interrupt the release it will delay it [indefinitely] or existing testing will suffer. Treat the release branch as you would master. It is sacred. Only bug fixes are allowed against it.

  1. Branch longevity

If your release branch is lasting months, your release cycle is too long. I've worked in places where the release cycle is, on average every 3 weeks and other places where we released every couple of days. 3 weeks should be ample time to QA and UAT a release branch. If you're looking at a longer cycle then I would argue that the company isn't agile and

  1. git-flow is the wrong branching strategy (doubtable, it works in almost any scenario as long as it's carefully managed)

  2. You seriously need to challenge the company on why they have such a long cycle

  3. (most likely) - you don't understand Git-Flow

    1. CI

I have used Git-Flow very successfully with CI. Although this has mainly been Jenkins and Bamboo, it also works with Travis CI.

A Git Hook based on commits is exactly how any branch build works. The best examples I have used automatically build as soon as a commit (or series of commits) is pushed to the remote, then the hook kicks in and calls the CI platform. The CI platform then finds the related job (either using in-built templates or using a 3rd party module) to trigger the build.

My own personal setup is to trigger a local Jenkins instance when:

  • I create a branch (creates new job in local install of jenkins targeted for the current branch)
  • I commit (triggers local instance build of the current branch)
  • Local build passes, can auto-push to remote
  • I push new branch (creates targeted build in remote CI
  • I push commits (triggers remote CI targeted instance)
  • I delete local branch (deletes local job)
  • I delete remote branch (deletes remote job)
  • I raise merge request (soft merges feature/A into develop and tests - tests fail, merge rejects automatically)

This takes some configuration but it is possible with any modern CI platform.

Like anything else, the rules for using Git-Flow are only guidelines. There are no hard and fast rules. If you want a long lived release branch then that's your choice BUT unless you pay attention to them you will end up with a divergent codebase which will be hell to merge back together.

Git-Flow, like anything else that is born from *nix tooling, is simply a way of working and with it comes a great deal of choice. The tool and the workflow is nothing more than a wrapper on to GIT. How you choose to implement it is entirely up to you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top