We use git to keep track of changes we make to the model. Git is a revision control system, similar in purpose to SVN or CVS, but different in execution. If you're new to git, Github has some good documentation on setting up git, and gitref is a good quick-reference page and has an excellent git tutorial as well, the git project's documentation is a good resource for more in-depth details on git's workings, and Jan Krüger has a great git cheat sheet if one needs a quick reference.
The model repository is hosted by Github, a webpage that offers project hosting, as well as a bevy of tools for collaborating using git. Signing up, as well as hosting open source projects, is free, and we strongly recommend that collaborators sign up and use Github to assist in collaboration.
As of version 1.0.0 (Sep 2013), we've begun using Semantic Versioning to dictate model version numbers. Roughly speaking, version numbers consist of MAJOR.MINOR.PATCH, which are incremented when
MAJOR: when backwards incompatible changes are made
MINOR: when backwards-compatible functionality is added
PATCH: when backwards-compatible bug fixes are made.
The upshot of which is that your parameter files for model version
1.0.3
will not work with version 3.6.4
but will work
with 1.2.0
and 1.0.4
. If you are contributing, we
highly recommend you read the full SemVer specification.
The various versions of the model are marked in git with tags and can be reviewed on Github. Creating a new tag using git is straightforward, as is pushng the tag to a server:
$ git tag <tag-name>
$ git push <remote> <tag-name>
For example, supose we wanted to tag version 1.2.5, and push this tag to Github. At the shell we would type:
$ git tag v1.2.5
$ git push origin v1.2.5
which create the new tag, and sends it to the server.
Git's a flexible tool, which allows for a wide variety of work flows. Here's one which serves well for working with DEBaM and DETIM, i.e. if you want to contribute to the model by adding a feature, fixing a bug, editing documentation etc.
This only needs to be done the first time you start working with the model code; your fork will need to be updated occasionally to keep up to date with changes to the model, but you shouldn't need to re-fork the model.
How to create a fork: - Go to the model github page - Click on 'Fork'. This makes your own fork and at the same time copies the entire github model repository (including all branches) to your fork on github.
open terminal
$ git clone https://github.com/USERNAME/meltmodel.git
(Replace 'USERNAME' with your user name) Now you a local copy of your Github fork on your computer.
Say we want to add a new parameterization to compute longwave radiation, at the terminal (in folder meltmodel) make a new branch by typing:
$ git branch longwave
$ git checkout longwave
or, we can use the equivalent one-liner:
$ git checkout -b longwave
this will create a new branch, entitled longwave
and make that the active branch. Now, any changes which we commit to
the repository will be made to the new branch only.
The title of the branch longwave
is just an example, we could have
named the new branch anything, but we should give the branches
descriptive names.
At the command line, you can view the status of your files via the command
$ git status
Editing a tracked, but unmodified, file will change its status to modified, but these changes will not be tracked by Git until we commit them to the repository.
So how do we make a commit? Assuming we've made some changes,
we need to assemble a commit, by staging changes. Git requires
you to explicitly add every change that you want included. Suppose
we've only changed the source file radiat.c
and
the corresponding header file radiat.h
.
* Stage These files are currently untracked by Git. We add them
by staging them using the git add
command.
$ git add radiat.c radiat.h
longwave.c
we add that file including the header file,git status
to see the status of
the local repository, if we decide we'd like to undo some changes
or add more changes we still can before we make our commit,
but we will need to stage these changes too, with another
git add
command.Commit Once we've staged a collection of changes, we need to save these changes to the repository. Simply type
$ git commit
a text editor will open, and you should enter a descriptive message
describing the changes made by this commit.
If your message is sufficiently terse, you can enter it at the
command line, with the -m
option:
$ git commit -m "Added new longwave radiation parameterization."
Now, if we check the status of the local repository using git status
we will see that the changes we committed are no longer marked
as modified.
Make More Changes and Make More Commits: We can now happily edit away, making more changes at will. Repeat steps 4 and 5 as needed, making new commits as you go.
Push Branch to Github: At some point you'll want to push the entire branch that contains your the changes on local computer to your own github repository. This will allow you to access the content from any other computer and also makes your changes visible to others. If you have pulled the source from your own fork on Github (see step 2 above) this is as easy as
$ git push origin longwave
where "longwave" is our example of the name of the branch and needs to be replaced by the name of the branch you are using. This tells git to push the changes you've made on the branch "longwave" to the remote server named "origin" which is, by default, the server you cloned the model from.
Until you are sure that you want to include the changes you've made in the master branch of your fork, it's wise to keep your edits isolated in the branch you've made. Continue this by repeating steps 2 - 5. When your code is ready to be included in the model's "official" code (master version), proceed to 8.
How to make a pull request: Go to your fork on github and change into the branch that you want to merge with the 'official' master version. click on 'submit pull request'.
This will notify the model administrators and create a page where people can discuss the proposed model changes. Note that it is up to the administrator to merge your changes into the 'official' master version. You don't have permission to do so and need to contact R. Hock.
Deleting a Branch:
Git's branches are easy to make, and easy to delete. If we decide that
the changes we've made on the branch aren't to your likeing, and
want to get rid of them entirely, we can delete the entire branch.
Here we're going to delete the longwave
branch.
Deleting a Branch Locally: We should first make sure that we're on a different branch from the one we're deleting. Also you have to commit all your changes or stash them before you can switch branches:
$ git checkout master
we can then delete the branch in our working copy
$ git branch -D longwave
Deleting a Branch on your fork on Github: The above only deletes the local version of the branch on your computer. If this branch has been pushed to your fork on Github, we can delete it there too. This should be done with caution.
$ git push origin :longwave
Merging Branches on your own fork:
We've gone over making branches to isolate changes, and deleting branches when
those changes don't work out, so it remains to combine branches when changes
do work out. It is recommended to merge branches locally and then push the merged
branch to github.
When there are no conflicts, merging with git is simple. Suppose
we've finished making changes on our longwave
branch, are pleased with
the results, and want to include the code in the master
branch of the code.
Assuming we're on the longwave
branch we first checkout the master
branch
$ git checkout master
And then merge the longwave
branch into it:
$ git merge longwave
Assuming no conflicts were found, your master branch will now have
new commits in it which incorporate the changes made on the longwave
branch.
It's a good idea to look over the new code to make sure that the merge resulted
in the code you expected, and that nothing surprising broke.
If you are merging two branches and both have had commits made on them since the branch, it's possible that git will have some trouble resolving the changes made, and you will need to fix the offending lines by hand. Git's good about telling you this though and about parking up your files to help you find points of contention.
Merge Pull Requests: In case you receive a pull request for any of your branches of your fork on Github you can decide to merge them into your code repository (master or any other branch you may have). Two ways to do so:
Manually merging via the commandline:
Following the example we have been working with, to merge
the changes we've made on the longwave
branch into the master
branch we would do the following
from the command line:
$ git checkout master
$ git merge longwave
Push to Github: Finally, to push the changes we've made up to Github, we would do the following from the command line.
$ git push origin master
Remote Repositories:
Becasue Git is a distributed system, it gives us the abolity to interact with
multiple "central" repositories. That is, my local clone of the repository
can simultaneously retrieve and send commits to/from my fork on github,
the official fork on github, someone else's fork, or remote repositories
located elsewhere. On our local machines, we use the git remote
subcommand to manage how our local copy of the code interacts with remote
copies on servers or elsewhere.
Adding the Official Repo to your Local Repo: Assuming that you have cloned you local copy of the code from your own fork on Github, we'd like to be able to pull code from the official reposotory, say when bug fixes occur. In the commandline, change directories into your local copy of your repository. At the commandline enter:
$ git remote add regine https://github.com/regine/meltmodel.git
You can double check that the remote has been added correctly using
$ git remote -v
which will list the remote repositories availibe to your local repo.
Remotes are useful for working with other collaberators as well, the general syntax for adding remotes is:
$ git remote add <remote_name> <remote_clone_url>
Pulling Changes From a Remote:
When we want to bring our local branch up-to-date with a remote branch
(say bring master
up to date with the official master
branch)
we use the git pull
command.
First, checkout the branch we will pull onto
$ git checkout master
Then pull changes from the remote regine
$ git pull regine
Pushing Changes To a Remote:
The other obvious operation we'd like from remotes is the ability
to push changes up to them. We do this via the git push
command.
The only difference between pushing to your fork, on remote origin
and pushing to any other remote is that we specify the remote's name
$ git push <remote_name>
This assumes that you have write access to the remote repository you are pushing to.
An Example: Suppose we've cloned the official repository, made some changes, and decided to fork the project on Github and push our chages to it. We can start by renaming the official remote
$ git remote rename origin regine
Then add our remote, giving it the name origin
$ git remote add origin https://github.com/<user_name>/meltmodel.git
Now we can push the changes we've made on our branch to our fork:
$ git push origin --set-upstream <branch_name>
by specifying --set-upstream
, we're telling git that your local branch
specified by origin
.
Caveat Git versions prior to v1.8.x may have issues using HTTP(S) addresses. To deal with the you will either need to update your version of git, or use ssh remotes. Github has decumentation to setting up ssh remotes here.
Further information about the remote tool can be found at Git Ref.
Making Model Changes:
Create a new branch:
$ git branch <branch_name>
Check out a branch:
$ git checkout <branch_name>
Make Changes/ Add files
$ git add <new/changed_filename>
Check on what's added/changed/staged
$ git status
Commit changes
$ git commit
Push to Github
$ git push origin
Delete a local branch
$ git branch -d <branch_name>
Merge one branch (source) into another (target)
$ git checkout <target_branch_name>
$ git merge <source_branch_name>