How to contribute
Obtaining MESA
There are two ways to submit changes to MESA, depending on who you are.
MESA developer
If you are a MESA developer then you will have commit access to the MESA repository on Github. You must create an account on GitHub. The MESA organization is called MESAHub. After you are registered on GitHub, you can be invited to the organization.
Non-MESA developer
For those who do not have commit access to the main MESA repository you will need to fork MESA and make your changes in your fork. Once you are happy with your changes you can submit a pull request against the main MESA repository. At this point your contributions will be reviewed by a MESA developer who may or may not accept the pull request. If they accept it then it will be merged into MESA.
More details can be found in the contribution documentation
Set up Git
Follow this GitHub guide to set up git.
When instructed to install git, it is likely simplest to do so using your system package manager on Linux (e.g., apt, yum) or a macOS package manager (e.g., Homebrew, MacPorts).
Note
This documentation will mainly describe command line use of git. However, there are many graphical git clients available. For example, GitHub has its own desktop app. (See also Graphical interfaces).
Install Git LFS
MESA uses Large File Storage (LFS), a git extension that allows us to easily store and version the large microphysics data files.
Obtain and install Git LFS from its website. You only need to do Step 1 in the Getting Started section. Step 2 has already been done for MESA.
Download the MESA repository
Make a git clone of the MESA repository. (This is analogous to svn
checkout
.) This will automatically fetch the files from git LFS. To
clone over SSH, do:
git clone git@github.com:MESAHub/mesa.git mesa
This will create the MESA repository in a directory named mesa
.
For this to work you will need to have setup ssh keys and added them to your github account:
Making changes to MESA
Note
Git is a powerful and complex tool. This section is an extremely incomplete introduction to git on the command line. There are many online resources at the tutorial level (e.g., git, from GitHub, from Bitbucket) and beyond.
The conventional name of the remote repository is origin
. The
main
branch is the development version of MESA.
Note
Prior to 2020, the default branch of a git repository was often
canonically named master
. You may still see this used in some
older materials. The MESA default branch is main
.
MESA development uses the following branching model:
main — Default branch. This is equivalent of SVN trunk. Small/innocent changes can directly be made in
main
. Themain
branch should always be passing the test suite.feature branches — Branched from
main
for large/significant changes. Feature branches should be pushed to GitHub and then merged via a pull request. Confirm that the test suite passes before merging. This also gives an opportunity for other developers to comment on the changes.release branches — Branched from main at the time of the first release candidate. Any final fixes can be backported (cherry-picked or merged) to
main
.
The line between what should be a feature branch / pull request and what’s committed straight onto the main branch can be drawn based on how disruptive a change is expected to be. If it has the potential to break test suite cases, don’t commit it directly to main. Use a branch.
Making a commit
When you want to add a new file or add changes to a file that is already tracked by git, do:
git add <filename>
Note that this is different from svn add
, which is only used to
track new files.
Once you have added your desired changes:
git commit -m <message>
If you want to commit all your changes to files already tracked by git, you can skip the git add and do:
git commit -a -m <message>
Note that this is different than svn commit
, as it only alters
your local repository. It does not transmit your changes to the
remote repository.
Removing or moving files
To remove a file:
git rm <filename>
Remove a folder:
git rm -rf <filename>
To move a file (or folder):
git mv <filename_old> <filename_new>
After changes you still need to make a commit:
git commit -m <message>
or:
git commit -a -m <message>
You should use the git versions or rm/mv whenever possible as git can then track the changes better and it is less likely to cause issues when merging branches.
Fetching others changes
When you want to get others’ changes:
git pull origin main
The first argument is the remote repository (origin
= GitHub).
The second argument is the branch name. If you want to get changes
from a non-default branch (i.e., not main
), see Branching.
If you have made changes to a branch and pull from a branch that others have independently modified, git must decide how to reconcile the divergent branches. In order to avoid unnecessary merges (thereby giving a simpler, more linear commit history), it is suggested that you default to rebasing your changes. Rebasing means that git will pull others’ changes and then replay your changes on top of them. If the changes conflict, you will have a chance to resolve the conflicts. To make this the default behavior, issue the following command while your current working directory is in the MESA git repository:
git config pull.rebase true
You can also pass --rebase
, --no-rebase
(combine changes with
a merge commit), or --ff-only
(refuse to pull if there are other
changes) on the command line to override the configured default per
invocation.
Note
Alternatively, one can select this behavior on a per-branch basis.
For example, the following setting will only rebase by default when pulling into main
:
git config branch.main.rebase true
With this setting alone, doing git pull origin main
on a
feature branch would result in a merge commit and not a rebase.
If you want to get others’ changes, but not immediately update your local repository to match that content:
git fetch origin
To prune out branches that may no longer exist in the remote repository:
git fetch --prune
Checking out a revision
To checkout out a previous version of the repository you first need the hash of the commit.
This is a 40 character code looking like 37cbee26a70574189d2e6169594af360215e18b6
, luckily though you do not need the full 40
characters, you only need enough of the hash to be unique. This is usually only 6-8 characters long:
git checkout 37cbee26
This will return your local repository to the state is was in the commit given by 37cbee26
, but with your current uncommitted changes
on top.
Restoring a file
Note
Recent versions of git include the new command git restore
that
splits out some of the functionality of git checkout
. (If you
already know how git checkout
works, you can also use that
command to accomplish the same goal.)
If you want to reset a file to its most recently committed state:
git restore path/to/file
The path/to/file
could also be something like the current
directory (.
) or a list of files (*.f90
).
git restore
can also be used to restore a file from another commit:
git restore --source=37cbee26 path/to/file
Branching
Note
Recent versions of git include the new command git switch
that
splits out some of the functionality of git checkout
. (If you
already know how git checkout
works, you can also use that
command to accomplish the same goal.)
If you decided to make a new branch this can be done with:
git branch mynewbranch
git switch mynewbranch
or:
git switch -c mynewbranch
Any changes you now make will not apply to main
but instead to mynewbranch
.
To delete the branch:
git branch -D mynewbranch
If you want to push that branch to GitHub to share it with others, do:
git push --set-upstream origin mynewbranch
This will create a new branch on GitHub named mynewbranch
and associate it with the local branch on your machine of the same name.
Note
Give the branch a short, descriptive name. To help others quickly
see who a branch belongs to, you can prepend your initials (e.g.,
jws/kap-compton
or rf/rates-nullify
).
Once you have set the upstream branch, you may omit the branch name when you push additional changes to this branch:
git push origin
or pull additional changes from others on this branch:
git pull origin
When you are ready to merge the changes from mynewbranch
into main
then push mynewbranch
to GitHub and make a pull request.
If someone else has created a new branch and pushed it to GitHub, you can switch to it with:
git checkout theirnewbranch
That shortcut command works when theirnewbranch
does not exist locally, but there does exist a tracking branch with that name in exactly one remote (i.e., in origin). This will check out the branch theirnewbranch
and associate it with the remote branch. This is equivalent to:
git switch -c theirnewbranch --track origin/theirnewbranch
Stashing changes
Lets say you are working on the code and suddenly a bug report comes in and you decide to fix that code first before you finish your current work. Because your initial work is still in progress you want to save it but do not want to commit it yet. This is where git stash comes in:
git stash
This saves your current changes that have not been committed in a stash
and resets your repository to the
current committed version. You can then make your changes to fix the new bug then re-apply the stash on top of the new
commit:
git stash apply
This way your in progress changes do not get mixed in with unrelated changes. Note the stash
still exists, so you need to drop
it once you no longer need it:
git stash drop
You may have multiple stashes at once, in which case they are indexed by:
git stash ${X}
where X
is a number starting at 0 for the most recent stash
.
Graphical interfaces
Not everything needs to be done by command line. There are at least two GUI tools that are usually shipped with git,
git gui
and gitk
.
git gui
This provides a convenient interface for making commits. You can select which files to commit, which lines of which files, set the commit message, and make the commit.
gitk
This provides a convenient interface for viewing the history of the repository where you can view the commits, files changed, and commit messages.
gitk --all
By default gitk
only shows the current branch --all
shows all branches.
gitk path/to/file
Will only show the commits that change that file.
Git testing tips
git fetch --all
Fetches all commits over all branches
$(git log -1) == *'[ci skip]'*
Tests to see if we should skip testing the test cases. Note we still want to compile test MESA even if we skip the full test suite.
Pull requests
Preparing to make a PR
After you have made a branch and pushed it to GitHub (see Branching), the test suite will automatically be run and the results reported to MESA TestHub. You should wait for the TestHub to confirm that the test suite is passing before merging a PR.
If the changes in your branch conflict or interact with changes that
have occurred on main
, it is recommended that you merge main
into your
branch (or rebase your branch to the tip of main
) before issuing the
PR. This allows you to handle conflicts in advance and ensure that the
test suite will remain passing after you merge your branch back into
main
.
When you merge main
into your branch, it is also advisable to add [ci optional]
to the commit message.
That way the optional inlists will be tested when the commit is tested.
Making a pull request
After you have made a branch and pushed it to GitHub (see
Branching), you can issue a pull request for the code on your
branch to be merged into main
.
If you have recently pushed a branch, GitHub will offer you the option to make a PR on the main page. Otherwise, the most general approach is to visit the new pull request page, select the code you want to merge from the ‘compare’ dropdown, and then click the green ‘Create pull request’ button. You will be asked to provide a title and description for the PR as well as other optional information (like selecting a reviewer). Then click ‘Create pull request’. Once you have made the PR, it will show up in the list of pull requests.
A set of code reviewers is automatically selected for each PR based on the contents of the CODEOWNERS
file. For now, this request for review can be treated as a heads up that there are changes in a part of the code you may be interested in. Reviewers are not required to complete requested reviews and reviews are not required before a PR is merged from a MESA developer. However, please exercise good judgment and solicit feedback before merging, especially for significant changes or changes that you feel uncertain about. You may want to ping relevant individuals or channels in Slack.
Merging a pull request
Once the code is ready, it can be merged by visiting the page associated with the PR (e.g., https://github.com/MESAHub/mesa/pull/161).
GitHub offers several strategies for merging pull requests. Each one may be appropriate in different circumstances. The merge strategy is selected by using the dropdown arrow on the big green button at the bottom of the PR.
If the PR is a small set of simple, well-contained changes, the ‘Rebase and merge’ strategy is recommended. This will take the commits and add them to the tip of
main
, ensuring that the commit history ofmain
remains linear.If the PR is a set of changes whose detailed history is not relevant, the ‘Squash and merge’ strategy is recommended. This will take the commits, combine them into a single commit, and then add it to the tip of
main
. This strategy is most useful when the series of individual commits simply reflects the (possibly wandering) path to achieving the final cumulative change.If the PR is a set of changes where each commit is a meaningful, self-contained change, but the cumulative change is not simple enough for the ‘Rebase and merge’ strategy, then the ‘Create a merge commit’ strategy is appropriate. This will preserve the full history of your branch when it is joined with
main
. If a change has this level of complexity, it is also recommended that its interaction withmain
should be tested by mergingmain
into the branch.