-
Notifications
You must be signed in to change notification settings - Fork 313
Quick start to CTSM development with git
The following instructions describe the basic development workflow in generic terms. If you prefer to see a tutorial-style specific example, see the May 30, 2018 tutorial, "Using git and GitHub with CTSM".
If you are new to git, we recommend the following resources (roughly in order from shorter to longer and more comprehensive):
- For a glossary of common terms used in git and GitHub documentation, see the GitHub glossary.
- For a brief overview of git and GitHub, including example workflows and links to more in-depth resources, we recommend GitHub's Git Handbook.
- For a hands-on introduction, we recommend Software Carpentry's git tutorial.
- For a slightly more extensive set of tutorials, see Atlassian's git tutorials.
- For a comprehensive reference, we highly recommend the free pdf book Pro Git. The first three chapters, along with sections 6.1 and 6.2 on GitHub, are particularly useful if you're getting started with git. [1]
Git also offers extensive built-in help, although it can be hard to understand until you are familiar with basic git concepts:
git help git help COMMAND
[1] | You can skip the last section of chapter 3, on rebasing, until you have more experience with git. It's easy to cause problems for yourself or others with rebasing. Furthermore, we recommend avoiding rebasing if you have done any scientific runs with a branch: rebasing rewrites history, which can make it impossible to reproduce exactly what you've done before. |
First, make sure you have set up your GitHub and git environments, as described in Recommended git setup. If you have used GitHub and git for other projects, it's likely that you've already done everything necessary in this respect.
The main CTSM repository (https://github.com/ESCOMP/CTSM) is read-only for most people. Thus, to do development that you want to share with others (or share with yourself easily across machines), you will need to create a fork of this repository on GitHub. To do so, click the "Fork" button at the top right of https://github.com/ESCOMP/CTSM, and create a fork in your personal GitHub user account. You only need to do this once: you'll have one GitHub fork to hold all of your branches. [2]
[2] | The ESCOMP CTSM repository is public. This means that your fork will also be publicly readable (but only writeable by you, unless you add collaborators). If you want to keep your developments private for some time, you can avoid pushing them to your fork. In fact, since git is a distributed version control system, you can get its full benefits without pushing your changes at all: you can just commit them to the local repository that exists on your machine and wait to push them until you're ready to share them. If you want to share them with a small group of people, you can create a private repository on GitHub or elsewhere - but you cannot use GitHub's "fork" functionality to do this. |
We strongly encourage collaborators to open an issue in the early stages of a project in order to get feedback from other CTSM scientists and software engineers and to avoid duplicated work. You can open an issue here: https://github.com/ESCOMP/CTSM/issues/new/choose.
Feel free to describe your plans in as much or as little detail as you'd like initially. Some things that can be helpful to describe are:
- Relevance of the proposed science changes
- Planned structure of the implementation, if known (a new module or class, new subroutine in an existing module, changes to an existing subroutine, etc.)
- Files you are planning to change, if known
- Collaborators (if any)
Git lets you manage multiple branches within a single local clone. In some circumstances this can be helpful. However, checking out a different branch in an existing clone can interfere with any ongoing cases that you created from that clone, and can make it hard to reproduce what you've done later. So, as a general rule, we recommend having a separate clone for each branch. [3]
To create a new clone with a new branch, starting from the master branch, do the following. First, make a new clone of the main repository [4]:
git clone --origin escomp https://github.com/ESCOMP/CTSM.git ctsm_MYBRANCH cd ctsm_MYBRANCH
(where you should use some descriptive name in place of MYBRANCH
).
Then create a new branch for your work:
git checkout -b MYBRANCH master
Finally, to get the submodules you'll need to run:
./bin/git-fleximod update
The above git checkout
command assumes that you want to create your branch
starting from the latest version of the master branch. The master branch contains the
latest development code, and is often the best starting point for new
developments. Starting from master (as opposed to a release branch) is also important if
you plan to get your work integrated into the main CTSM repository in the future.
However, in some cases you may want to branch off of a different point. For example, you
may want to branch from a particular tag (for example, if you have run a control
simulation from that tag and now you want to run a modified version). In that case, you
can replace master
with the tag you want to start from. If you are unsure where to
branch from, please ask us.
Do not commit changes directly to the master branch (or any similar branches that you got from ESCOMP/CTSM, such as release branches). While we have set up safeguards to ensure that you cannot accidentally push your changes back to the ESCOMP repository, you will create headaches for yourself if your version of master diverges from the true master branch.
You can then use the standard git workflow to commit your changes:
[Make some changes] git status git add ... git commit
If/when you want to share your changes, you can do so with [5]:
git remote add GITUSER [email protected]:GITUSER/CTSM.git git push -u GITUSER MYBRANCH
replacing GITUSER
with your GitHub username.
[3] | Once you have become comfortable with git, a good alternative to having separate clones is to use git worktree. This gives you a separate working directory that shares branches, remotes, etc. with your original clone. |
[4] |
Doing the initial clone of the main ESCOMP repository (rather than of your personal fork) ensures that the master branch is set up to track ESCOMP's CTSM master branch. This connection to ESCOMP's master branch is typically what you want: trying to work with the master branch on your fork can create confusion and errors. The instructions here will give you two remotes whose names have
unambiguous meanings: one named |
[5] |
You only need to do the The |
For long-term developments, it is often the case that you want to keep your branch up-to-date with the latest changes on master. This can be because you want to incorporate bug fixes or new features. In addition, if you are planning to eventually merge your branch back into the main repository (via a pull request), then it's a good idea to periodically pull in updates from master to reduce the potential for conflicts in the end. For the latter case, a good time to do this merge from master is just before you start making new changes to your branch after you have stepped away from it for some time.
Before following the instructions in this section, run git status
to make sure
you don't have any uncommitted changes. If you do have uncommitted changes, either commit
them or undo them before proceeding. [6]
Also, you generally should NOT update to the latest version of master if you have ongoing cases that are being run out of this directory. Existing cases can be in an inconsistent or invalid state after some code updates, so any cases created with your old code version should no longer be used with the updated version. If you need to maintain the usability of old cases, then you should create a separate git clone for this update and any further development.
The first step is to get the latest changes from ESCOMP/CTSM:
git fetch escomp
Before merging these changes into your branch, it's helpful to know what tag your branch is up-to-date with and what the latest tag is on master. This can be done with [7]:
git describe git describe escomp/master
The first command will tell you the tag your branch is up-to-date with. The output of this
command will look like ctsm1.0.dev060-2-g5428b8e2
, where the first part, before the
dash (ctsm1.0.dev060
) tells you the tag your branch is up-to-date with, the second
part (2
) tells you how many commits ahead of that tag you are (i.e., commits on your
branch that aren't in that tag), and the third part (g5428b8e2
) gives the ID of the
current commit on your branch (ignore the first g
, which just tells you this is a git
repository).
The second command will tell you the latest tag on master. The output of this command will
typically be shorter, like ctsm1.0.dev068
, which tells you that the latest tag on
master is ctsm1.0.dev068
. So in this case, when you merge the latest version of master
into your branch, you will get all of the changes that have been made between
ctsm1.0.dev060
and ctsm1.0.dev068
[8].
You can then merge the latest version of master into your branch with:
git merge escomp/master
If the merge went smoothly, your editor should pop up, letting you type a commit message
(or just use the default commit message, which describes the merge you just did). When you
save and close your editor, the merge is complete; you can confirm this by rerunning git
describe
, which should now show you as being up-to-date with the latest tag from
escomp/master
. You should then rerun git-fleximod
in case
.gitmodules changed in the merge.
However, it's also possible that there were conflicts that git couldn't resolve. Git will give you a message about this, and will leave the merge in an uncommitted state. The Pro Git book gives some information on resolving conflicts, as does a Tutorial we put together. Bear in mind, though, that conflict resolution can be challenging and error-prone; this is a common source of bugs in the model. If you're not sure of what you're doing, ask for help. After resolving conflicts, it's a good idea to check the diffs in the conflicted file, both from the previous version of your branch and from master (see the tutorial link above for more details).
If you're not ready to deal with the conflicts right now, you can back out to the state you were in before starting the merge with:
git merge --abort
[6] | For help with undoing uncommitted changes, see the Pro Git book. |
[7] | The commands in this section assume that your branch is currently checked out. That will typically be the case if you are following the instructions in this guide. |
[8] | Occasionally, master will contain commits beyond the last tag. For CTSM, these
untagged changes are typically just documentation or other minor changes. Even if
git describe shows that escomp/master has commits beyond the last tag, you
can still follow all of the instructions here. |
You need to rerun git-fleximod
whenever .gitmodules has changed (unless you have already manually updated the
relevant submodule(s) to have the correct branch/tag checked out). Common times when this
is needed are:
- After checking out a new CTSM branch/tag
- After merging some other CTSM branch/tag into your currently checked-out branch
If you'd like to get your developments onto the master branch, you will need to submit a GitHub Pull Request. To do this:
- Push the latest version of your branch to your fork, as described in Basic development workflow
- Navigate to your fork on github
(
https://github.com/GITUSER/CTSM
) - In the "Branch" pull-down menu on the right, select the correct branch
- Next to the "Branch" pull-down menu, click the button labeled, "New pull request"
- In the "Open a pull request" page, confirm the forks and branches being used for the pull request. On the left you should see "base fork: ESCOMP/CTSM" and "base: master". On the right you should see "head fork: GITUSER/CTSM" and "compare: MYBRANCH" (where GITUSER will be your git username, and MYBRANCH will be the branch you'd like brought to master).
- Enter a short but descriptive title for this pull request
- In the comment box, give a more detailed description of this pull request
- Click the green "Create pull request" button
- Optionally, once the pull request is created, you can comment on individual lines. To do this, click on "Files changed" (just below the title of the pull request). As you hover over changed code, you'll see a blue button with a "+" appear; if you click this, you can enter a comment for that specific change.
This article gives some useful tips on how to be a good author of Pull Requests.
After you submit a pull request, your changes will likely be reviewed by one or more people. If they ask for changes, please go ahead and make whatever changes you are able to yourself. You can then commit your changes (either as a single commit or multiple commits) and push them back to your fork. As soon as you push the changes back to your fork, GitHub will notice this; it will automatically update the Pull Request and notify reviewers and anyone else who is watching the Pull Request.
At that point, reviewers will typically look at your latest changes and then either approve the Pull Request or ask for further changes.
-
General
-
Documents
-
Bugs/Issues
-
Tutorials
-
Development guides
CTSM Users:
CTSM Developer Team
-
Meetings
-
Notes
-
Editing documentation (tech note, user's guide)