- We want to be able to release a version on demand.
- We need to support multiple versions when required.
- We need a solution that scales with our current and future needs.
GitFlow
- feature/... – feature branches for separate development and testing, created mostly from develop.
- bugfix/... – bugfix branches for separate development and testing, created mostly from develop (or from the relevant release branch).
- release/V2026.Q1..., release/V2026.Q2... – previous (major/minor) releases (hotfixes, required changes).
- master – current version (2026.Q3...).
- develop – current & next release – integration testing of development & fixes.
- Create a feature branch (from develop).
- Loop (implment → fix → test → commit).
- Merge into develop.
- Loop (hand over for testing → develop → fix → test → commit → merge).
- Accept.
- Optionally merge to master and maybe release/V2026.Q2.
- Release, or wait for the next release.
-
It heavily depends on estimations, planning, number of testers, etc. – introducing many points of failure,
because it tightly couples releases to the current state of develop:
- You must correctly estimate which features will be finished in time.
- You must know QA capacity in advance.
- You must assume that priorities won’t change too much mid‑cycle.
- Any task that slips the release or fails QA can potentially require additional work from the whole team.
- Any task changes or cancellations require additional protocols for removing changes from develop. This is directly counter‑productive: it adds work exactly when you have the least time. As a result, GitFlow makes easy tasks easier and hard tasks harder.
- Any task that is in develop needs tracking for completion / non‑completion.
- You are basically working on experimental code – there is no presumption of code quality on develop.
- Any changes that are reverted from develop require excessive work to make them visible for merge again and to monitor them. To do this properly, you would need to double‑check all changes that came afterwards.
- Any trial or experimental changes are risky because they automatically pollute the workspace once merged – including changes that seemed trivial at first.
- Partial changes that technically "work" but alter application behaviour are painful, because we need to extract them back out – and they may already be integrated into other changes.
- Any easy collaborations between teams are basically dead – any commit can entangle a developer in the full release cycle.
- Branching out from develop for a new version makes changes incompatible with previous versions by default.
- develop is not stable enough to test, and not isolated enough to experiment.
- develop is an integration branch, a testing branch, a next‑release branch, and a staging area for partially complete work.
- Pollution by unfinished behaviour, expensive rollbacks, and coordination overhead.
- It also creates a false signal – a low number of merge requests does not indicate quality; it may simply mean that people silently pull from a polluted develop, absorbing partial or untested changes. Potential conflicts and behaviour changes get hidden inside these pulls instead of being visible as explicit merge conflicts – it’s a kind of survivorship bias.
If your process requires:
- tracking reverted features,
- monitoring merge visibility,
- remembering which tasks were undone,
- struggling with pollution from old branches,
- constant firefighting QA on develop just to keep it usable,
- your branching strategy is compensating for missing isolation,
- you are moving merge costs into intricate bugs in production,
- development time is silently moved into excessive Scrum meetings and coordination.
CleanCut
- V{versionPrefix}/feature/{committer}/... – feature branches for separate development and testing.
- V{versionPrefix}/bugfix/{committer}/... – bugfix branches for separate development and testing.
- unstable/... – prefix for branches with changes that are unstable, missing time/resolution or are outside current support scope. This is a place where we park partial work when fature/bug priority changes or the team has no time to finish it. The team typically reviews these branches after each sprint.
- backup/... – prefix for sandbox, feature, backup and bugfix branches and for changes temporarily outside current consideration.
- release/V2026.Q1..., release/V2026.Q2... – release branches of previous minor versions (hotfixes, required changes for those versions).
- master – current version: changes that are already released, waiting for release, or being tested for stability before release.
- quarantine – optional branch that collects merges and commits before they are moved to master and tested as a single set.
- sandbox – integration test, development, and fixing. After each minor version it is moved to backup/.../sandbox and recreated from master (or quarantine) with relevant branches added. Recreation can also be done on demand when pollution happens.
- develop – integration development – optional branch, used only in new/greenfield projects that are intentionally messy, evolving fast, and where the consequences of bugs are minimal.
- Stable branches in CleanCut are master and release/... (and optionally support/...).
- A new minor(quarterly) version only requires: creating a new branch release/V2026.Q3 from master, then increasing the master version to 2026.Q4.0, and optionally recreating sandbox (develop).
- New feature/bugfix branches should be created from a release or master branch, not from sandbox nor develop.
- Before pushing any work into a stable branch, it should be squashed into one or a few comprehensive commits. Optionally, you can create a new branch with S{s} added into the branch name, where {s} is the squash version. This helps track history and creates a natural manual for similar changes.
- Re-merge into sandbox after squash to ensure that feature changes created from master do not introduce collisions – this is purely a structural compatibility check.
- Branches should contain a control file that prevents invalid merges, for example blocking merges from sandbox to master.
- Best practice for working on the same area is: either working sequentially (one after another) or creating a shared work branch for all participants.
- Creating a work/test branch from sandbox (develop) is acceptable when researching the source of a bug that appeared after testing and does not occur in stable branches.
- Including version and committer in the branch name allows easy monitoring of unfinished/dropped work, and gives hints about estimation when picking up the task again.
- In some cases the sandbox branch can be omitted.
- In some cases only the master branch is used.
-
To minimize collisions when possible:
- library changes should be done separately,
- non-conflicting / incremental changes (e.g. configuration/properties) should be done separately.
- Create a feature/bugfix branch from the lowest required stable branch: master, release/V2026.Q2, release/V2026.Q1.
- Loop (implement → fix → test → commit).
- Squash if needed.
- Merge into sandbox for integration testing.
- Loop (hand over for testing → to sandbox → fix → test → commit → merge).
- Accept.
- Squash (final squash if needed).
- Merge into each required stable branch, starting from the lowest required: release/V2026.Q1, release/V2026.Q2, then master (or quarantine if used).
- Release decision.
- This model ensures that merge conflicts are indicators of possible problems, not the source of them.
- sandbox can be discarded at any moment.
- Cleaning up old branches and monitoring is extremely easy.
- "one feature" = "one commit" on stable branches, making history and rollbacks simpler.
- Control files reduce accidental or invalid merges that break the model.
- Experimental/complex work can be dropped and picked up at any time, balancing evolution and collisions.
- Isolation of unfinished / unstable work.
- Branch naming clearly states intent and ownership.
- Conflicts in this model help prevent bugs.
When CleanCut is used as a flexible framework, it can become a single company‑wide convention. The only mandatory rule is to create feature/bugfix branches from stable branches, along with the naming convention.
- Only rare changes → don’t use sandbox – sandbox is only needed when you want a sandbox/integration area.
- Only one version → use only master –
release/V2026.Q1,release/V2026.Q2are for reference only. - Need more detailed history → skip squash – squash is not required; it’s just recommended for easier rollback and analysis.
- Great tests / strong CI → skip quarantine
- Need fast release → skip quarantine
- No need to keep unfinished/parked work → drop unstable branches – features are small and either merged or abandoned quickly.
- In the simplest case, CleanCut shrinks to: master as the only stable branch, short‑lived feature/bugfix branches from master, optional squash before merge..
- Very simple / small projects
- CleanCut: no develop, no sandbox, no quarantine, no unstable, no backup, no multi‑version release/...
- GitFlow: with a dirty develop.
- Single product, strong CI, one or two supported versions
- CleanCut: no develop, no quarantine unless needed.
- GitHub Flow: a minimal alternative when multi-version support is not needed.
- Complex, enterprise-style, multi-version, limited QA
- CleanCut: no develop.
- GitFlow: typically with a shared develop branch.
- When master is our main focus, "create a feature/bugfix branch from the lowest required stable branch" can be simplified to: start from the primary branch only. The primary branch may be named main, master, or trunk, as long as it is clearly understood and consistently used.
- release branches could be clarified to release & support:
release/V2025.Q4...,support/V2026.Q1...,support/V2026.Q2....
0 comments / komentarz(y):
Post a Comment