Git branching model strategy
Asked Answered
P

2

9

We are trying to follow the gitflow branching model, but with a twist.

We have have four servers environments where the product can be deployed to, each server serves a purpose : development, internal testing, external testing, and production.

  • DevServer, where developers test their different features, while developing. Developers cannot test locally on their machines, they have to make their changes on the DevServer to be able to test
  • TestServer, where QA testers test multiple features once developers are done
  • ReleaseServer, where releases are tested in isolation before moving them to production
  • ProductionServer. The production server

We are trying to make the merging / conflicts resolution as easy as possible, so we created two extra branches which is not part of the gitflow model.

Normal gitflow branches

  • develop
  • master (matches 'ProductionServer')
  • featureXXX
  • releaseXXX (weekly releases are deployed to 'ReleaseServer')

But also these two branches which is not standard and might need to change...

  • dev-release (copy of DevServer)
  • test-release (copy of TestServer)

Then process is then as follow:

  • developer create their 'featureXXX' from 'develop'
  • multiple developers merge their different 'features' into 'dev-release' branch, and 'dev-release' branch gets released to the 'DevServer' where all the developers can then test their different features. Not all these features will be in the same next release
  • Once the developers are happy with their dev testing above, they merge their 'featureXXX' into branch 'test-release', and this gets deployed to 'TestServer'. Not all features here will be part of the same next release.
  • Once testing on 'TestServer' is done for featureXXX, the developer can close their featureXXX into 'develop'.
  • Developer then either create a new 'releaseXXX' or merge their 'featureXXX' into an existing 'releaseXXX'.
  • The 'releaseXXX' branch is deployed to to 'ReleaseServer' and tested.
  • Once 'releaseXXX' testing is signed off, 'releaseXXX' is merged into develop and master, and deployed to 'ProductionServer'

Are we messing up the whole gitflow model?

Here is our brancing process: enter image description here

Pneumodynamics answered 27/6, 2016 at 8:10 Comment(1)
This question is related - and has relevant answers: #31339271Pneumodynamics
J
13

To answer your question, no you're not messing up the gitflow model - more extending it to meet your needs.

By coupling environments to a given branch, you're giving yourself much more flexibility when it comes to building releases. i.e. lets say you have two non-dependent features (Feature 1 and 2) in progress, both of which have been merged into your 'TestServer' branch. If Feature 1 fails testing, Feature 2 can still be progressed further without Feature 1 - this is because your merge into 'TestServer' is a one-way merge - nothing comes out, no history. Instead, your Feature 2 branch is merged into 'develop' and eventually 'master'.

We're in the process of adopting/developing a similar strategy to yourself. The key requirement for us is to accommodate the unavoidable cherry-picking of features. Note that our solution, although rather complex, has been designed for an enterprise application, serving as a platform for multiple services owned by multiple business-owners and utilise multiple in-house frameworks..

Environments

  • QA: for developers to ensure that their feature is testable.
  • Stage: for project managers / test managers to smoke-test prior to UAT testing by the various 'Business Owners'
  • UAT: for full testing and business sign-off by the 'Business Owners'
  • BETA: merely a test of deployment/release
  • LIVE: ..

These environments are grouped into two categories, 'in-test'(QA, Stage and UAT) and 'production' (BETA and LIVE).

Branches

Feature prioritisation can change often, from testing issues through to regulatory restrictions/requests. To accomodate this, multiple branches are created to represent the environment/categories as follows:

  • Master: Represents the last production release
  • Release-Candidate: A collection of features for the next production release
  • UAT: Represents UAT environment
  • Stage: Represents 'QA' and 'Stage'
  • Feature-xxx: For feature development

We also utilise a HotFix branch from Master as required, and prepare production releases in a 'Pre-Production' branch (correcting missed version increments etc - minor stuff).

A diagram of our Branches in use: A diagram of our Branches in use:

Branching and Merging / WorkFlow

  1. We always branch new Features from Release-Candidate as this branch always contains the 'Committed for production' features. Nothing leapfrogs once the commitment for production has been made.

  2. Once a feature is ready for testing, it's merged (one-way) into 'Stage'. This triggers a CI build and deploys to QA.

  3. If the QA server looks stable, the developer triggers an automatic deployment to Stage.

  4. If changes are required then make them in feature and repeat. If OK for business testing, then merge from Feature to UAT. This deploys to UAT.

  5. If feature fails business testing, then make changes in feature and repeat. If feature is delayed then take no action. If feature is OK and signed-off, then merge to Release Candidate.

  6. Once collection (1 or more) of features are in Release-Candidate, trigger production deployment by merging from Release-Candidate to Master (via Pre-Production).

  7. Deployment failed, then HotFix. If OK, deploy to Live.

Our workflow, using TFS, looks like this:

Our workflow, using TFS, looks like this:

Release workflow

And finally, each deployment to an environment/category would look like this:

Flow of deployment

Julianejuliann answered 27/6, 2016 at 15:53 Comment(1)
Wow, I just want to really thank you for the in depth answer and explanation!! I haven't documented our process as well as you, and it really helps seeing the diagrams. I am marking yours as the answer, because I know now that it is OK to create the one-way branches (which is for long and short running features to be tested), and only merge features into release when it has been signed off. (Although I am going to keep our strategy as is, and will post it here soon)Pneumodynamics
L
0

Git is a version control system. It maintains the source code and their changes. The development stops on the development stage. After that, the source code shouldn't change.

When you move your project to the next stage (test, release, prod) you should not deliver source code, rather binaries build from tagged version, because:

  • the source code does not change in different environments,
  • two builds might provide two different binaries (change on the dependencies)
  • the maintenance of different versions will be difficult. For example,
    • multiple version of the project needs supporting
      • Framework projects
      • A/B testing
      • ...
    • bugfix. Imagine when the new release on the test server, and you need to make hotfix from production. This hotfix needs to go through the same flow (test, release, prod). So you need to overwrite the test branch with the bugfix and after merging back to the new release version. Which is not obvious, not necessary, and might lead to having a different code initially meant to be. Actually, with every merge, after the development, there is an unnecessary risk the source code might be different that meant to be. And you might need to solve merge conflict in prod.

So it might not interfere with the git-flow model, but I think these points worthy to consider. Actually, I'm not a big fan of the git-flow strategy. If you have a minute give a chance on these:

https://barro.github.io/2016/02/a-succesful-git-branching-model-considered-harmful/ https://trunkbaseddevelopment.com/

Leonidaleonidas answered 25/4, 2018 at 16:48 Comment(2)
"Regardless, teams perform a full “pre integrate” build (compile, unit tests, integration tests) on their dev workstations before committing/pushing for others (or bots) to see." I think that statement necessitate a few assumptions: 1) the product can be packaged in binary form, no distributed dependencies or persistent data/services needed 2) the unit/integration tests are comprehensive 100%, no manual checking requiredTrout
@Khoa, 1; not sure why do you have this assumption, but which form do you want to distribute your product? 2; yes you should have comprehensive tests, but it's an independent metric from the branching strategy. You can have manual check as well, as much as your product require.Leonidaleonidas

© 2022 - 2024 — McMap. All rights reserved.