Developer’s guide

Meso-NH is build upon many contribution since 30 years. As the code is growing and shared with increasing models and contributors, a number of coding norms must be followed.

Branch Management Strategy

Version 1.0 — 2026-05-22

1. General principles

Note for end users: this document targets developers who work directly with Git branches. Users who wish to modify the source code for their own simulations without contributing back to the repository could use the make user mechanism, which provides an isolated working copy without requiring Git knowledge. A documented pathway from make user to a proper Git branch exists for modifications that mature into shareable contributions.

  • MNH-master accepts direct pushes for minor changes. Substantial changes go through a Merge Request (MR). See section 8 for the distinction.

  • Release branches are protected against direct writes. Any change must go through an MR or a cherry-pick/merge from a validated commit (from master or another release branch).

  • Every temporary branch is associated with a GitLab issue. The issue is mandatory whenever a branch is created — the issue number is part of the branch name. The only exception is trivial fixes applied directly on MNH-master without a dedicated branch.

  • Temporary branches are deleted after merge. They have a limited lifespan and do not accumulate. GitLab can handle this automatically via the “Delete source branch” option in the MR, which is recommended. Otherwise the developer or the maintainer who performs the merge is responsible for deleting the branch.

  • The stability of MNH-master is ensured by collective discipline, not by strict technical protection. The basic rule: if a direct push risks breaking the build for everyone, open an MR.

  • A compilation check is automatically run on all branches at every push and before any merge. More advanced CI policies (non-regression tests, validation) are defined in a dedicated document.


2. Permanent branches

MNH-master

The main branch and the sole convergence point for all developments. It must always be in a compilable and functional state. It is recommended (but not mandatory) to branch off MNH-master when creating all temporary branches, except for bugs specific to a release branch.

Rules:

  • Direct push allowed for minor changes (see section 8).

  • Substantial changes go through an MR.

  • Each release is marked by a tag (see section 7).

Release branches MNH-X-Y

A release branch is created at each minor version release (X.Y.0). It is maintained in parallel with MNH-master for a minimum of 2 years after the release of the next minor version, to receive bug fixes only.

Naming: MNH-X-Y (e.g. MNH-6-0, MNH-6-1)

Dots are replaced by hyphens to avoid ambiguities in shell and Git tools.

Rules:

  • Direct push forbidden — any change goes through an MR or a cherry-pick.

  • Only bug fixes may be integrated, never new features.

  • Note: a performance optimisation may be considered a bug fix if it does not modify simulation results and the changes remain minor; otherwise it is a new development and must be integrated into MNH-master for the next minor version.

  • Fixes applied to a release branch are ported to MNH-master and other release branches if necessary (see section 6).

Lifecycle:

Release of Meso-NH 6.1.0
  → creation of tag PACK-MNH-V6-1-0
  → creation of branch MNH-6-1
  → 2-year support starting from the release of version 6.2.0 (bug fixes only)
  → at the end of the support period: archiving (branch set read-only for everyone,
    including maintainers, via Settings → Repository → Protected branches)

3. Temporary branches

There are only two types of temporary branches: dev and bug. The presence or absence of a version number in the name immediately indicates the target branch.

Development branches — MNH-dev-{issue}-{title}

For any new feature, refactoring, performance improvement, or any substantial code change.

Recommended starting point: MNH-master. It is possible to start from a release tag (e.g. PACK-MNH-V6-1-0) if the developer prefers a validated and immutable starting point. In that case, the final merge into MNH-master will require integrating all commits made on master since that tag — the longer the branch has lived, the harder this becomes. Regardless of the origin, regular resynchronisation with MNH-master (rebase or merge) is strongly recommended to limit drift.

Merged into: MNH-master via MR

Examples:

MNH-dev-42-turb-new-feature
MNH-dev-67-output-hdf5-12
MNH-dev-103-new-machine

Bug branches on master — MNH-bug-{issue}-{title}

For fixing a bug present on MNH-master (and possibly also present on release branches).

Created from: free starting point (MNH-master (recommended), tag, or release as needed)
Merged into: MNH-master via MR or direct push if the fix is trivial
Then ported to: the affected release branches via cherry-pick (if a single commit) or merge (if multiple interdependent commits). Squashing commits at merge time is recommended to simplify porting.

Examples:

MNH-bug-89-crash-restart-mpi
MNH-bug-94-wrong-pressure-output

Bug branches on release — MNH-X-Y-bug-{issue}-{title}

For fixing a bug present on one or more release branches, but absent from MNH-master.

Important note: if the bug also affects MNH-master, refer to the previous section (no version number in the branch name).

Created from: the affected release branch (e.g. MNH-6-0)
Merged into: that same release branch via MR
Then ported to: the affected release branches via cherry-pick (if a single commit) or merge (if multiple interdependent commits). Squashing commits at merge time is recommended to simplify porting.

Examples:

MNH-6-0-bug-112-bad-cherry-pick-radiation
MNH-6-1-bug-118-segfault-nested-domain

The version number in the name is mandatory in this case: it immediately signals that the branch does not target MNH-master and avoids any confusion when running git branch -a.


4. Naming convention — summary

Type

Pattern

Example

Main branch

MNH-master

MNH-master

Release branch

MNH-X-Y

MNH-6-0

Development

MNH-dev-{issue}-{title}

MNH-dev-42-turbulence-tke

Bug on master

MNH-bug-{issue}-{title}

MNH-bug-89-crash-restart-mpi

Bug on release

MNH-X-Y-bug-{issue}-{title}

MNH-6-0-bug-112-bad-cherry-pick

Format rules:

  • Separator: hyphen - only (no dots, no underscores).

  • Short title: 2 to 4 words, lowercase, separated by hyphens.

  • The issue number is mandatory for all temporary branches.

  • No special characters, no spaces.

Immediate reading of a branch name:

  • Starts with MNH-dev- → development, targets master.

  • Starts with MNH-bug- → bug fix, targets master.

  • Starts with MNH-X-Y-bug- → bug fix, targets release X.Y only.


5. Development workflow

1. Open a GitLab issue describing the feature or improvement.
   → A dedicated issue template for development is not yet available at the time
     of publication of this document.
2. Create a branch MNH-dev-{issue}-{title} from MNH-master (or a release tag).
3. Develop, commit regularly with clear messages.
4. Open a Merge Request into MNH-master.
   → Mention "Closes #N" in the description to close the issue automatically.
   → Consider using the "Squash commits" option to produce a single clean commit,
     which simplifies the history on MNH-master.
5. If possible, review by at least one other developer.
6. Green CI + approved review → merge into MNH-master.
7. Delete the temporary branch.

6. Bug fix workflow

The starting point is free — what determines the naming is the destination, i.e. whether MNH-master is affected by the bug or not.

Case 1 — Bug present on MNH-master and on release branches

This is the most common case.

1. Open an issue using the bug report template (bug_report), identify the affected versions (e.g. master, 6.0.5, 6.1.0).
2. Create MNH-bug-{issue}-{title} from MNH-master, a tag, or an affected release.
3. Fix the bug.
   → If working directly on MNH-master (no bug branch): direct push if trivial, MR otherwise.
   → If working on a bug branch: MR into MNH-master (direct push not applicable).
4. Port the fix to all affected branches (MNH-master if needed, MNH-6-1, MNH-6-0…)
   via cherry-pick (single commit) or merge (multiple interdependent commits).
   This is the responsibility of the developer who fixed the bug.
5. Document the fixed versions in the issue before closing it.

GitLab provides a “Cherry-pick” button directly on the merged commit, making the porting straightforward and error-free. If the bug branch contains several commits, it is recommended to squash them when merging (into MNH-master or into a release branch) using the GitLab “Squash commits” option, to simplify subsequent porting to other branches. If squashing is not desirable, a direct merge is preferable to multiple individual cherry-picks.


Case 2 — Bug present on MNH-master only

Recent regression, not yet present in any release.

1. If the bug is trivial, apply the fix directly on MNH-master (no issue or branch needed).
2. Otherwise, open an issue and create MNH-bug-{issue}-{title} from MNH-master.
   → No version number in the branch name (master-only bug).
3. Fix the bug, MR or direct push depending on complexity.
4. No cherry-pick needed.

Case 3 — Bug present only on one or more release branches

Regression introduced by a cherry-pick, bug in code already removed from master…

1. Open an issue using the bug report template (bug_report), confirm that master is not affected.
2. Create MNH-X-Y-bug-{issue}-{title} from any affected release branch.
3. Fix the bug, MR into that release branch.
4. Port the fix to other affected releases if needed,
   via cherry-pick (single commit) or merge (multiple interdependent commits).
   This is the responsibility of the developer who fixed the bug.
5. Document in the issue.

Decision table

Bug present on

Starting point

Branch name

Propagation

master + releases

MNH-master, a tag, or a release

MNH-bug-{issue}-{title}

Cherry-pick or merge to all affected branches

master only

MNH-master or a recent tag

MNH-bug-{issue}-{title}

None

one or more releases, not master

any affected release branch

MNH-X-Y-bug-{issue}-{title}

Cherry-pick or merge to all affected releases


Backport tracking in issues

Each bug issue must explicitly mention:

  • The affected versions.

  • The fixed versions as cherry-picks or merge are applied.

GitLab labels should list the Meso-NH version numbers affected by the bug.


7. Tags and version numbering

The numbering follows the X.Y.Z scheme:

  • X: major version (incompatible changes, deep refactoring).

  • Y: minor version (new features, backward compatibility intended but not guaranteed).

  • Z: bug fix (fixes only, no new features).

Applying tags

Event

Tag

Tagged branch

Minor version release

PACK-MNH-V6-1-0

MNH-master

Bug fix on release

PACK-MNH-V6-1-1

MNH-6-1

Intermediate versions (i.e. preparing a new release)

PACK-MNH-VX-Y--Z-rc01 (2 hyphens between Y and Z for alphanumeric sort)

MNH-master or MNH-X-Y


8. Branch protection rules

MNH-master — relaxed protection

Direct push is allowed for minor changes. The practical rule:

Direct push acceptable

Merge Request mandatory

Typo fix, comment

New feature

Trivial fix (a few lines, obvious)

Refactoring

Changes to interfaces or namelists

Non-trivial bug fix

Basic rule: when in doubt, open an MR.

Release branches MNH-X-Y — strict protection

Direct push forbidden. Any change goes through an MR or a cherry-pick/merge from a commit already validated (on master or on another release branch). This strictness is justified by the long lifespan of these branches and their users’ dependency on them.

Continuous integration policy

A compilation check is the minimum CI requirement and applies to all branches without exception. It is the basic safety net that ensures no push silently breaks the build for the rest of the team.

More advanced testing levels — non-regression tests, physical validation — are not yet fully defined. The intended direction is a three-level funnel:

Level

Content

Trigger

Branches

1 — Compilation

Build with standard gfortran

Every push

All

2 — Quick tests

Short test cases, basic numerical non-regression

MR open/update

MNH-dev-*, MNH-bug-*, MNH-X-Y-bug-*

3 — Full validation

Complete reference test cases, multiple compilers

Manual or merge on master/release

MNH-master, MNH-X-Y

The detailed CI policy will be described in a dedicated document when finalised.

[!note] At the time of publication of this document, the CI pipeline was not yet in place.


9. Schematic overview

Developments

        %%{init: { 'theme': 'base', 'gitGraph': {'mainBranchName': 'MNH-master', 'parallelCommits': true, 'showCommitLabel': true}} }%%
gitGraph
   commit
   commit id: "PACK-MNH-V6-1-0" tag: "PACK-MNH-V6-1-0"
   branch MNH-dev-42
   checkout MNH-dev-42
   commit id: "dev-42a"
   commit id: "dev-42b"
   checkout MNH-master
   commit
   commit
   branch MNH-dev-67
   checkout MNH-dev-67
   commit id: "dev-67a"
   commit id: "resync master"
   commit id: "dev-67b"
   checkout MNH-master
   merge MNH-dev-42
   merge MNH-dev-67
   commit
    

Bug fix — from MNH-master

Bug present on master, MNH-6-0 and MNH-6-1.

        %%{init: { 'theme': 'base', 'gitGraph': {'mainBranchName': 'MNH-master', 'parallelCommits': true, 'showCommitLabel': true}} }%%
gitGraph
   commit
   branch MNH-6-0
   checkout MNH-6-0
   commit
   checkout MNH-master
   commit
   branch MNH-6-1
   checkout MNH-6-1
   commit
   checkout MNH-master
   commit
   branch MNH-bug-89
   checkout MNH-bug-89
   commit id: "fix bug #89"
   checkout MNH-master
   merge MNH-bug-89
   checkout MNH-6-1
   commit id: "cherry-pick fix #89 for 6-1"
   checkout MNH-6-0
   commit id: "cherry-pick fix #89 for 6-0"
    

Bug fix — from a release branch

Bug present on master, MNH-6-0 and MNH-6-1, fix made from MNH-6-1.

        %%{init: { 'theme': 'base', 'gitGraph': {'mainBranchName': 'MNH-master', 'parallelCommits': true, 'showCommitLabel': true}} }%%
gitGraph
   commit
   branch MNH-6-0
   checkout MNH-6-0
   commit
   checkout MNH-master
   commit
   branch MNH-6-1
   checkout MNH-6-1
   commit
   branch MNH-bug-89
   checkout MNH-bug-89
   commit
   commit id: "fix bug #89"
   checkout MNH-6-1
   merge MNH-bug-89
   checkout MNH-master
   commit id: "cherry-pick fix #89 for master"
   checkout MNH-6-0
   commit id: "cherry-pick fix #89 for 6-0"
    

Bug fix — specific to a release branch

Bug present only on MNH-6-0.

        %%{init: { 'theme': 'base', 'gitGraph': {'mainBranchName': 'MNH-master', 'parallelCommits': true, 'showCommitLabel': true}} }%%
gitGraph
   commit
   branch MNH-6-0
   checkout MNH-6-0
   commit
   branch MNH-6-0-bug-112
   checkout MNH-6-0-bug-112
   commit id: "fix bug #112"
   checkout MNH-6-0
   merge MNH-6-0-bug-112
   checkout MNH-master
   commit
    

Coding best practices

General

These guidelines apply mostly to every FORTRAN sources in src/ MNH, SURFEX, PHYEX, ACLIB, LIB.

File structure:

  • Check if the function you code is already coded

  • Avoid CONTAINS routines, create a new fortran routine file

  • For new file, keep the common structure with an updated statements for the LICENCE and documentation

Code ergonomy:

  • Maximum 132 characters per line, use &

  • Code in CAPITAL characters

  • Comments in lower-case characters

  • No blank line, use !

  • Remove debugging PRINTs and WRITE before committing

  • Comment your code !

Clean code:

  • Remove debugging PRINTs and WRITE before committing

  • Remove unused local variables

  • Remove unused dummy variables

  • Remove unused module variables (USE MODD …)

  • Select the variables used: USE MODD TOTO, ONLY : MYVAR

Variables:

  • Variables names must be consistent through subroutines (a variable must be easily found with grep)

  • All variables must be declared, use IMPLICIT NONE

  • Allocatables must be deallocated

  • Pointer must be initialized by NULL()

Reproductibility:

  • Use the parallelizaded version of basic functions (functions ended by ll such as MAX_ll or SUM3D_ll)

  • Avoid anticipated exit of a loop with EXIT, CYCLE, RETURN statements

Variables names

Variables first letter(s) must follow the DOCTOR norm:

Norm DOCTOR

Type/Status

INTEGER

REAL

LOGICAL

CHARACTER

TYPE

Global

N

X

L (not LP)

C

T (not TP, TS, TZ)

Dummy argument

K

P

O (not PP)

H

TP

Local

I

Z (not IS)

G (not GS, ZS)

Y (not YS, YP)

TZ

Loop control

J (not JP)

/

/

/

/

Extra rules for PHYEX

The externalized atmospheric physics PHYEX has extra rules in order to comply with all the models using PHYEX (AROME, HARMONIE-AROME, etc). These rules are more strict in order to transform automatically the code for GPU applications. The general idea behind these rules is that all the physics can be run with arrays written in one physical dimension (the vertical axis). The fortran raw code is written in 2D or 3D in a way that automatic functions (e.g. written in python) can read the fortran code and transform it to another fortran code that can be run on any type of GPUs. The previous general rules applies to PHYEX.

The following extra rules apply on PHYEX/ :

Variables:

  • Do not use allocatables

  • Dimensions of dummy argument arrays must be explicit : no (:,:), use the structure D%

  • No variables from modules can be imported except variables declared with the PARAMETER attribute. Put the variable in a type received by the subroutine interface

  • Use loop index JIJ for computation on horizontal dimensions

  • Use loop index JL on KSIZE microphysics computation point

  • Horizontal dimensions arrays are packed into one dimension : instead of A(D%NIT, D%NJT, D%NKT), use A(D%NIJT, D%NKT) where D%NIT, D%NJT, D%NKT are physical dimensions in x, y, z directions and D%NIJT = D%NIT*D%NJT

Subroutines:

  • Do not use functions returning arrays, use subroutines

  • Avoid CONTAINS subroutines, if really needed, the local arrays of the subroutines must have different names than the hosting subroutine or than other contained subroutines Statements

  • All calculation on arrays must show explicit dimensions. Instead of A = B + C, write : A(:,:) = B(:,:) + C(:,:) even for initialization

  • Do not use nested WHERE, convert it to DO…IF…

  • Temporary Do not use ANY, COUNT functions on arrays of horizontal dimensions

  • Temporary no (:) on TYPE%VAR

  • Compilation keys must be avoided. If really needed, the statements betwen ifdef and else must not split a statement

Extra rules for ACLIB

ACLIB is shared with other models. Specific rules must be followed:

  • Use explicit dimensions in variable declaration

  • Do not add Méso-NH specific modules/variables into ACLIB, but add variables through the interfaces instead. If a new specific module is needed, make sure that this module is Méso-NH agnostic (not dependent of other Méso-NH specific modules that would be incompatible with other host models)

  • Use dedicated ACLIB custom types as it is implemented (e.g. use CST_ACLIB for constants and not MODD_CST from MesoNH world)

  • Internal routines in src/ACLIB must be agnostic from parallelization as much as possible to ease future use of cross-codes in different host models.

How to contribute to the code ?

Meso-NH packs VX-X-X are divided into two categories :

  • major release-pack: X and Y of VX-Y (e.g. 5.4, 5.5, 5.6, etc)

  • bugfix release-pack: Z of VX-Y-Z (e.g. 5.4.1, 6.0.1)

A call of contribution is done for a major release-pack. For bugfixes only, you can contribute anytime.

Clone the git repository

Contributions are merged into the official branches via the official repository. Follow the instructions to clone the repository here. Then:

  • If you have a JANUS account (CNRS), log in and create a fork of the repository. Code in your own branch.

  • If you do not have a JANUS account, contact us (mesonhsupport .at. utoulouse.fr) and we will send you a token to be able to create a personal branch in the official repository.

Once your developpement is ready, create a merge-request.

Major release-pack

A major release contains several scientific and technical changes and numerous bugfixes. The time frequency of a major release is about one over 12 to 18 months depending on the amount of contributors. In the case of a major release-pack, please follow these guidelines :

  • Merge the master’s branch into your work before sharing your branch with git pull. Resolve conflits if any and test the compilation.

  • New feature: you must share at least one new test case related to your work with python3 plots showing the interesting variables related to your new work.

  • Major modification of a current part of the code: you must share at least one new test case with python3 plots showing the interests variables related to your new work and to have tested your branch on 2 other cases that is impacted by your development (see the Namelist catalogue)

  • Provide a contribution to the user’s guide (this website) and scientific guide.

Bugfix release-pack

A bugfix release contains a sufficient number of minor bugfixes to justify a new release, or a hot bugfix that may impact a large number of users. The time frequency of bugfix can vary to a few days up to 12 months depending on the stability of the current pack release (usually a few months). Please follow these guidelines:

  • Merge your branch on the last version of the master’s branch with git pull. Resolve conflits if any and test the compilation.

  • only commits with bugfixes are asked. If your bugfixes are in a developpement branch, create a bugfix-branch and cherry-picks only bugfix commits.

Warning

Contributions of branches with major developments would be declined and postponed to the next call of contributions for a major release.