- Do not merge into dev for deployment.
- deploy a feature branch
- only deploy feature branches which have a fast-forward only merge from the tip of the dev branch.
- every deployment burns the test environment to the ground, (with the possible exception of deploying from the the same "feature" branch).
- QA sign off, is the quality gate for allowing a feature to deploy to UAT.
- Only with QA and UAT signoff does a feature move to dev for deployment
- Essentially dev represents the next releasable product.
Obviously there are a number of issues with this.
- QA and UAT must signoff before merging
- Big bang merges.
- All other features must re-undergo QA/UAT as merges will likely introduce bugs.
- The problem has been pushed one branch deeper, how do you efficiently merge "feature" branches.
- The QA systems only every see "feature" branches, unless double deployments are done.
- All dev work is done on the dev branch.
- The dev branch is releasable at anytime.
- This implies that every commit passes all current unit/integration/other automated tests.
- Features are guarded by "feature toggles" with each toggle supplied by a configuration file with the default of being disabled.
- Progression tests can be associated with the toggle, when all are defined and green the "feature" is deployable.
- QA, and UAT can accept a feature by updating the deployment configuration file
- Production can rollback a feature by toggling it in the configuration.
Obviously there are a number of issues with this:
- Diligence to cleanup and not reuse old feature toggles to prevent incidents like those that afflicted Knight Capital.
- Issues determining dead code form not yet enabled features.
- Increased Risks associated with features controlled by configuration.
Personally use both techniques in-so-far as they are more a benefit than a hindrance.
If something is risky, and probably won't make the code-base. Feature Branches are your friend. Should it not work out, which is the admitted potential, the branch can be discard with no further issues. The big-bang merge is a problem, but that can be avoided more-or-less by daily pulls from the development branch into the feature branch.
In contrast Feature toggles are great for low-risk changes, new functionality, or decommissioning functionality. Low-risk changes by definition usually cosmetic, or on the periphery of the system core, so switching them on and off is reasonably safe even when toggled incorrectly. New Functionality, and functionality decommissioning are also good examples as they allow a border to be constructed between good and bad parts of the system, permitting a change back to before as necessary.