Contributing to MOM6

Marshall Ward


Presentation is available at

The MOM6 Repository


Contained in the MOM6-examples repository

The MOM6 Consortium



Get the repository:

$ git clone --recursive

This creates a remote to NOAA-GFDL named origin.

$ git remote -v
origin (fetch)
origin (push)

Go to GitHub, fork MOM6, and create a new remote


  1. Log into GitHub, go to MOM6:

  2. Fork MOM6 to your account:

  3. Create a remote to your new GitHub repo:

    $ git remote add marshall
  4. Sync to the remote:

    $ git push marshall dev/gfdl


You want to start a new project! Create a new branch:

$ git checkout dev/gfdl       # Switch to dev/gfdl
$ git pull                    # Sync with origin
$ git branch my_feature       # Create a new branch
$ git checkout my_feature     # Switch to new branch

Changes to my_feature will not alter dev/gfdl.

Changing the Code

Add a welcome message:

diff --git a/src/core/MOM.F90 b/src/core/MOM.F90
index 267a162b0..17d5259c8 100644
--- a/src/core/MOM.F90
+++ b/src/core/MOM.F90
@@ -1912,6 +1912,8 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, &

   CS%Time => Time

+  print *, "Welcome to MOM6!"
   id_clock_init = cpu_clock_id('Ocean Initialization', grain=CLOCK_SUBCOMPONENT)
   call cpu_clock_begin(id_clock_init)

Or use your patch from "MOM6 internals"

Diagnostic patch

diff --git a/src/core/MOM_CoriolisAdv.F90 b/src/core/MOM_CoriolisAdv.F90
index 154db3eaa..00606a3d8 100644
--- a/src/core/MOM_CoriolisAdv.F90
+++ b/src/core/MOM_CoriolisAdv.F90
@@ -78,6 +78,7 @@ type, public :: CoriolisAdv_CS ; private
   !>@{ Diagnostic IDs
   integer :: id_rv = -1, id_PV = -1, id_gKEu = -1, id_gKEv = -1
   integer :: id_rvxu = -1, id_rvxv = -1
+  integer :: id_ens = -1
   ! integer :: id_hf_gKEu    = -1, id_hf_gKEv    = -1
   integer :: id_hf_gKEu_2d = -1, id_hf_gKEv_2d = -1
   integer :: id_intz_gKEu_2d = -1, id_intz_gKEv_2d = -1
@@ -188,6 +189,8 @@ subroutine CorAdCalc(u, v, h, uh, vh, CAu, CAv, OBC, AD, G, GV, US, CS, pbv, Wav
   real, dimension(SZIB_(G),SZJB_(G),SZK_(GV)) :: &
     PV, &       ! A diagnostic array of the potential vorticities [H-1 T-1 ~> m-1 s-1 or m2 kg-1 s-1].
     RV          ! A diagnostic array of the relative vorticities [T-1 ~> s-1].
+  real, dimension(SZIB_(G),SZJB_(G),SZK_(GV)) :: &
+    Ens         ! A diagnostic array of the enstrophy density [T-2 ~> s-2]
   real, dimension(SZIB_(G),SZJ_(G),SZK_(G)) ::     CAuS !
   real, dimension(SZI_(G),SZJB_(G),SZK_(G)) ::     CAvS !
   real :: fv1, fv2, fv3, fv4   ! (f+rv)*v [L T-2 ~> m s-2].
@@ -503,6 +506,12 @@ subroutine CorAdCalc(u, v, h, uh, vh, CAu, CAv, OBC, AD, G, GV, US, CS, pbv, Wav
       enddo ; enddo
+    if (CS%id_ens > 0) then
+      do J=Jsq-1,Jeq+1 ; do I=Isq-1,Ieq+1
+        Ens(I,J,k) = rel_vort(I,J)**2
+      enddo ; enddo
+    endif
     if (CS%id_PV > 0) then
       do J=Jsq-1,Jeq+1 ; do I=Isq-1,Ieq+1
         PV(I,J,k) = q(I,J)
@@ -925,6 +934,7 @@ subroutine CorAdCalc(u, v, h, uh, vh, CAu, CAv, OBC, AD, G, GV, US, CS, pbv, Wav
   ! Here the various Coriolis-related derived quantities are offered for averaging.
   if (query_averaging_enabled(CS%diag)) then
     if (CS%id_rv > 0) call post_data(CS%id_rv, RV, CS%diag)
+    if (CS%id_ens > 0) call post_data(CS%id_ens, Ens, CS%diag)
     if (CS%id_PV > 0) call post_data(CS%id_PV, PV, CS%diag)
     if (CS%id_gKEu>0) call post_data(CS%id_gKEu, AD%gradKEu, CS%diag)
     if (CS%id_gKEv>0) call post_data(CS%id_gKEv, AD%gradKEv, CS%diag)
@@ -1195,6 +1205,9 @@ subroutine CoriolisAdv_init(Time, G, GV, US, param_file, diag, AD, CS)
   CS%id_rv = register_diag_field('ocean_model', 'RV', diag%axesBL, Time, &
      'Relative Vorticity', 's-1', conversion=US%s_to_T)
+  CS%id_ens = register_diag_field('ocean_model', 'Ens', diag%axesBL, Time, &
+     'Enstrophy Density', 's-2', conversion=US%s_to_T**2)
   CS%id_PV = register_diag_field('ocean_model', 'PV', diag%axesBL, Time, &
      'Potential Vorticity', 'm-1 s-1', conversion=GV%m_to_H*US%s_to_T)

Verify Changes

Check status:

$ git status
HEAD detached at 5201c34a3
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
 modified:   src/core/MOM_CoriolisAdv.F90

no changes added to commit (use "git add" and/or "git commit -a")

Add file:

$ git add src/core/MOM_CoriolisAdv.F90

(Your file may be different)

Commit Changes

Commit the file:

$ git commit
[my_feature 02244bd3b] Enstrophy density diagnostic
1 file changed, 13 insertions(+)

Write a meaningful message:


Commits as email

  • Pre-git, commits were emails sent to maintainers

    • The message was the email (subject + body)
    • The patch was an attachment
  • Emails follow a standard format (RFC 5822)

    • "Lines … SHOULD be limited to 78 characters"
    • Subject reduced to ~50, leave space for hash

The closer you follow these rules, the better the results


Linus Torvalds, Linux OSS 2020

Commit messages to me are almost as important as the code change itself.

If you can explain the code change to me, I will trust the code.

Preparing the Pull Request

GitHub handles pull requests (PRs) between repositories.

$ git fetch origin dev/gfdl      # Update the target branch
$ git checkout my_feature        # switch to feature
$ git rebase -i dev/gfdl         # sync commits
$ git push marshall my_feature   # Push to personal repo

The PR moves commits between repositories.

Minor Edits

Use amends and force pushes for minor changes:

$ vim src/my_file.F90                     # Modify code
$ git add src/my_file.F90                 # Add to commit
$ git commit --amend                      # Change the commit
$ git push --force marshall my_feature    # Rewrite history


  • bugfixes
  • whitespace fixes
  • missing documentation

No one cares about typos! Don't put them in the history

Submit to MOM6


CI Testing

Continuous Integration checks all pull requests:


This one had problems!


GitHub Actions run the internal test suite

$ cd MOM6-examples/src/MOM6
$ cd .testing
$ make -j
$ make -j test
  1. dev/gfdl was out of date (missing MacOS fix)
  2. New variable needs to be in OpenMP directive

Gaea Regression


Final Approval

If all of the tests pass, then a human being (finally) evaluates the contribution.

Three options:

  • Merge
  • Rebase
  • Squash

Merges preserve commits; the others change hashes!

Merge Types

Merge Squash


GitHub Merge

GitHub merges are "non-fast-forward". They create a merge commit.


But FF merge is not always possible.


  • Use git to manage your contributions
  • Work on branches, submit back to dev/gfdl
  • Commits should be meaningful
  • Verified by automated testing