This document describes the branching patterns used across ECMWF repositories. ADR-001: Git Branching Model records the decision and rationale; this document is the normative operational procedure. Release version numbers and tags follow the Versioning policy (Semantic Versioning, clean x.y.z, no v prefix; prerelease x.y.z-upstream.N) — see also the tagging rules in External Contributions.
- Overview
- GitHub Flow
- Git Flow
- Choosing a Model
- Migration from GitHub Flow to Git Flow
- External Contractors
All ECMWF repositories adopt a hybrid approach: new repositories begin with GitHub Flow and may evolve to Git Flow as project needs grow. The decision to change branching model rests with the repository's GateKeepers. See ADR-001 for the full rationale.
| GitHub Flow | Git Flow | |
|---|---|---|
| Primary branch | main / master |
main / master + develop |
| Development branch | feature branches off main |
feature branches off develop |
| Release branch | — | release/* off develop |
| Hotfix branch | off main |
off main |
| Best for | Continuous delivery, small–medium teams | Scheduled releases, large teams, multiple versions |
GitHub Flow is the default for all new repositories. It uses a single long-lived branch (main or master) with short-lived feature branches.
main ──────────────────────────────────────────────► (production)
\ / \ /
feature/my-feature fix/issue-42
| Branch | Purpose |
|---|---|
main / master |
Always deployable; all releases are tagged here |
feature/<name> |
Short-lived branch for a feature or change |
fix/<name> |
Short-lived branch for a non-critical bug fix |
hotfix/<name> |
Urgent fix for a production issue |
- Branch — create a branch from
main:git switch -c feature/my-feature main - Develop — commit changes to the feature branch, keeping the branch short-lived and focused.
- Push and open a PR — push the branch and open a Pull Request against
main. Follow the PR guidelines. - Review — address reviewer comments; all CI checks must pass.
- Merge — a GateKeeper merges the PR into
mainusing the merge strategy agreed by the team (merge commit or squash). - Delete the feature branch after merging.
Releases in GitHub Flow are created directly from main:
- Ensure
mainis in a releasable state — all CI checks passing, release notes prepared. - Create and push a semantic version tag on
main:git tag x.y.z git push origin x.y.z - Publish any release artefacts (PyPI, container registry, GitHub Release, etc.) from the tag.
Note
If the repository uses automated release pipelines, the tag push typically triggers the pipeline. Check the repository's CI/CD configuration for details.
For critical production issues:
- Branch from the affected tag (or from
mainif the fix applies to the latest state):git switch -c hotfix/critical-bug x.y.z - Apply the fix and push.
- Open a PR against
main; follow the expedited review process agreed by your team. - After merge, tag the next patch release on
main(e.g.1.4.3→1.4.4).
Git Flow is adopted by repositories that require structured release preparation, multiple concurrent version support, or additional stability guarantees. The model is based on Vincent Driessen's branching model.
main ──────────────────────────────────────────────► (production tags only)
↑ merge ↑ merge
develop ──────────────────────────────────────────────► (integration)
\ / \ /
feature/login-ui feature/api-v2
release/1.2 ──────────────► (bug fixes only → merge to main + develop)
hotfix/1.1.1 ──────────────► (merge to main + develop)
| Branch | Branched from | Merged into | Purpose |
|---|---|---|---|
main / master |
— | — | Production-ready code; tagged releases only |
develop |
main |
— | Integration branch; latest delivered development changes |
feature/<name> |
develop |
develop |
Individual feature development |
release/<version> |
develop |
main + develop |
Release preparation; only bug fixes allowed |
hotfix/<version> |
main |
main + develop |
Urgent production fixes |
support/<version> |
main |
— | Long-term maintenance of older releases |
Important
Direct commits to main or develop are not permitted. All changes must go through Pull Requests.
- Branch from
develop:git switch -c feature/my-feature develop - Develop — make commits on the feature branch.
- Push and open a PR against
develop. Follow the PR guidelines. - Review — address reviewer comments; all CI checks must pass.
- Merge into
developand delete the feature branch.
- Create a release branch from
developwhen the set of features for the release is complete:git switch -c release/x.y.z develop - Bump the version number in the relevant files (e.g.
VERSION,pyproject.toml,CMakeLists.txt) and commit. - Stabilise — only bug fixes are committed to the release branch. No new features.
- Open a PR from
release/x.y.zintomain. All CI checks must pass. - Merge into
mainand tag the release:git tag x.y.z git push origin x.y.z - Merge
mainback intodevelop(via PR) to incorporate any fixes made on the release branch:git switch develop git merge --no-ff main - Delete the release branch.
- Publish any release artefacts (PyPI, container registry, GitHub Release, etc.) from the tag.
Note
Steps 5 and 6 are often handled together as part of the release pipeline. Check the repository's CI/CD configuration for details.
For critical production issues that cannot wait for the next scheduled release:
- Branch from
mainat the affected tag:git switch -c hotfix/x.y.z main - Bump the patch version and apply the fix.
- Open a PR against
main. Follow the expedited review process agreed by your team. - Merge into
mainand tag the hotfix release:git tag x.y.z git push origin x.y.z - Merge
mainback intodevelop(via PR) to ensure the fix is not lost in future releases. - Delete the hotfix branch.
Support branches provide long-term maintenance for older major or minor releases when users cannot immediately upgrade to the latest version:
- Create a support branch from the tag of the release to be maintained:
git switch -c support/1.x 1.9.0 - Apply fixes — cherry-pick or develop fixes on the support branch. Only critical bug fixes and security patches should be included.
- Tag patch releases directly on the support branch:
git tag 1.9.1 git push origin 1.9.1 - Support branches are long-lived — they are not merged back into
mainordevelopand are not deleted until the supported version reaches end-of-life.
Note
Support branches are independent from the main development line. Fixes applied
here must be separately cherry-picked to develop if they are also relevant
to the current version.
All repositories start with GitHub Flow. GateKeepers may upgrade to Git Flow when one or more of the following conditions are met:
- The repository has become operationally critical.
- The team size exceeds comfortable coordination limits (typically 8+ developers).
- The software requires explicit versioning or support for multiple simultaneous versions.
- The release process requires structured preparation with dedicated release stabilisation.
- Stakeholders require additional quality gates and formal release cycles.
- Deployment risk warrants additional safeguards and staging processes.
- Continuous delivery is not suitable for the software type.
The reverse is also possible: a repository using Git Flow may revert to GitHub Flow if the assessment of the above criteria reverses (e.g. the team shrinks or the project becomes simpler).
Refer to ADR-001 for the full analysis and decision rationale.
When upgrading a repository from GitHub Flow to Git Flow:
- Create a
developbranch from the currentmain. - Update the repository documentation and contribution guidelines to reflect the new workflow.
- Make
developthe default branch on GitHub so that new PRs target it by default. - Configure branch protection rules for both
mainanddevelop(changes only through approved PRs by GateKeepers). - Update CI/CD pipelines to support the new branching structure (e.g. test on
develop, release frommain). - Train team members on the new workflow and branch types.
- Document the decision and rationale (e.g. in the repository's CHANGELOG or wiki).
Contractors who need a tighter development loop or internal tagging for staged testing prior to formal ECMWF acceptance should follow the Integration Delivery Workflow. This covers:
- Forked development — using the contractor's fork as a working upstream.
- ECMWF integration branches — using
upstreamorupstream/<vendor>branches within the ECMWF repository. - Prerelease tagging — using the
x.y.z-upstream.Nconvention for contractor-side testing. - Submission and approval — how deliverables are formally accepted via PRs into
mainormaster.