LCSR Development Model
Source Code Repository Hosting
There are two servers which host open-source LCSR resources, depending on their licenses and intended audience. Code meant for public use under an open-source license is hosted on GitHub, while any private code or code which is published only for reference may be hosted internally on the LCSR GitLab. Limited-access to private source code resources may also be granted on a case-by case basis.
See Software for an index of all active JHU LCSR GitHub organizations.
Git Forking Model
LCSR repositories follow a centralized git development model. The "central" repository follows a strict branching and tagging model (described below), but both developers and non-privileged users are encouraged to develop in forks and submit pull requests for contributions. See the section on code reviews below for details on reviewing pull requests.
Git Branching Model
The branching model used by LCSR projects based on a simplified version of the Git Flow development model. All repositories hosted on LCSR GitHub organizations must conform to this branching model.
Similarly to Git Flow, we use following standard branches and branch types (described in more detail in the subsequent sections):
- master -- The main "operational" branch, which should never be broken.
- devel -- The "volatile" branch where the latest features and bugfixes get integrated for multiple users to test.
- feature-xxx -- Branches for features pending merge into
- hack-xxx -- Branches for variants of functionality which are done quickly for prototyping purposes.
Due to limited resources, we do not maintain release branches. As such,
bugfixes do not get pushed back into older versions of the code, they are only
devel before being merged into
master branch should always have an up-to-date
describes how to build it for the target platforms. This file should also
give a high-level overview of the design of the package.
This branch should be usable by people who expect the package to "just work" as described.
devel branch is used to test integration of features and
bugfixes before merging into
master. This branch should only be used
by people who are ready to debug problems which may arise and who aren't worried
about having to re-test their code.
Features are either backwards-compatible or non-backwards compatible. When making a pull request, it should be determined whether a feature will break anything as described below.
Backwards-compatible features include changes such as:
- Adding functionality
- Marking functionality as "deprecated"
- Refactoring -- restructuring without changing public interfaces
A non-backwards-compatible feature is any change which has any of the following effects:
- Removing functionality
- Changing the behavior of an algorithm
- Changing the behavior of an APIa
- Changing configuration properties
These branches are expected to be made when prototyping or pushing towards a
deadline. They're useful for archiving variants for experimental code which are
not intended to eventually be merged into
Version Tagging Model
Git tags are used to track breaking changes in a repository via a three-number
versioning system based on semantic versioning. In
semantic versioning, each tag is a 3-element version number
MAJOR.MINOR.PATCH. These elements are defined as follows:
MAJORversion when you make incompatible API changes,
MINORversion when you add functionality in a backwards-compatible manner, and
PATCHversion when you make backwards-compatible bug fixes.
Since we expect that research code developed by JHU LCSR will be more volatile
than that which is developed for end-users, we will use a different semantic
versioning system, called proto versioning. In this system, we also use a
3-element version number, but it corresponds to the following
MORTALversion when everything is changed, restructured, or otherwise broken
MAJORversion when you make incompatible API changes
MINORversion when you add functionality or fix bugs in a backwards-compatible manner
For repositories which you don't contribute to, you should either use the
master branch, or always use a tagged version. This will allow you to rely on
the code not changing.
Generally, if you're not responsible for maintaining a repository, you should develop in your own fork of the repository. This will allow you to have the freedom to store and work on your own experiments without breaking someone else's code.
On either GitHub or GitLab, you can fork a repository into your own account, and once
you want to contribute back, you can do so with a pull request into the original
If your code is out of date, you can merge or rebase changes from the original repository by adding it as a remote to your local clone:
git checkout feature-my-cool-thing git remote add upstream https://github.com/jhu-lcsr/repo-name.git git fetch upstream git merge upstream devel
As the maintainer of a repository, you're responsible for deciding when to
merge changes from the
devel branch into the
master branch and tagging
versions according to the versioning scheme described above.
For new repositories or repositories which aren't intended to be used by more
than one person, you can avoid maintaining separate
In order to make it clear that your repository is volatile, you should delete
master branch, and do all work directly in
For repositories where development has already been happening directly in
master, you can switch this with the following:
git checkout master # make sure you're on "master" git pull origin master # make sure you have the latest version of "master" git checkout -b devel # create a new branch called "devel" identical to "master" git push -u origin devel # push the new "devel" branch and set "origin" as it's upstream git branch -D master # delete the local "master" branch git push origin --delete master # delete the remote "master" branch
master and Tagging Versions
Occasionally, as features and bugfixes are incorporated
devel will be merged
master will be tagged with a new version. This is the
closest action in the LCSR Development model to a release.
git checkout master git merge devel git push origin master
To determine whether to increment
MINOR, you need to
review the changes since the last tag.
NOTE: Due to limited resources, it might not be possible to guarantee whether backwards-incompatible changes have been introduced. In this case, it is better to be conservative, and to increment the
In order to list all of the commits since the last tag, you can run the following after merging locally:
git log `git describe --tags --abbrev=0`..HEAD --oneline --decorate --color
feature-xxx branches which are backwards-compatible necessitate
MINOR version, and merging of non-backwards compatible
feature-xxx branches necessitate incrementing the
MAJOR version, and
MINOR version to
If it's clear that there has been a complete redesign of a package, it's
necessary to increment the
MORTAL version and re-set the
git tag $MORTAL.$MAJOR.$MINOR git push orign --tags
Continuous Integration Testing
Continuous integration testing can be used to guarantee that a repository builds and passes any available tests. A simple way to do this which works well with GitHub is with Travis.
The most important thing is to be consistent within a given project or repository.
Code reviews should be performed for all pull requests.