The Statnet Project endeavours to do most of its development in public. However, as its packages often incorporate unpublished research, some of the materials are temporarily kept private. GitHub does not allow branch-level access controls, so the project uses the following mechanism:

1 Invariants

The following describes the “invariants” of the private and public repositories: the relationship between their contents that must hold at all times. If ever one is violated, it should be restored as quickly as possible.

  1. Any entity in the public repository must also be in the private repository. This includes commits, branches, and tags.
  2. The commit log of the private repository must be a superset of that of the public repository.
  3. Branches and tags with the same names must point to the same commits.
  4. The private repository may have commits, branches, etc. that the public repository does not have. These must not use names used in the public repository.

A corollary of that is that the master branches of the two repositories are always identical: it is always possible to immediately push commits in PKG@master into PKG-private@master and vice versa; and similarly for release branches.

2 The dev branch

Normally, new features should branch from master and eventually be merged back into master for public release. However, a number of unpublished changes has accummulated, and they have gone into the dev branch that can be found in some private repositories. (It is, in turn, branched form master and kept in sync with it.)

This branch is intended to be temporary, and will eventually be merged into master. At this time, feature branches should only branch from dev if they absolutely require some feature in dev.

3 FAQ for Contributing Users (i.e., those with pull access to the private repositories)

3.1 I found a bug or have a feature request. Under which repository should I create an issue ticket?

  • Issues that pertain to the code both in public and in private repositories should be filed against the public repository.
  • Feature requests should generally be filed against the public repository as well. Exceptions include:
    • Feature requests that are specifically about some development exclusively in the private repository.
    • Feature requests that involve unpublished reasearch ideas.

4 Workflow for Developers (i.e., those with push access)

The following assumes that the user has push access to both the public and the private repository of a package and intends to operate on them directly, rather than, say, through pull requests. It is based on Michal Bojanowski’s instructions.

4.1 Local setup

  1. Clone the private repository:

    $ git clone git@github.com:statnet/PKG-private.git PKG

    the repository will be cloned into PKG. Cloning automatically defines a remote repository, called origin, which tracks the GitHub repository. This can be verified with:

    $ cd PKG
    PKG$ git remote -v
    origin  git@github.com:statnet/PKG-private.git (fetch)
    origin  git@github.com:statnet/PKG-private.git (push)

    You can see all the branches in your local clone is aware of with git branch -a:

    PKG git branch -a
    * master
      etc.

    We can see that locally I have master branch currently checkedout (marked with *).

  2. Add remotes pointing to the main public repo:

    We now add a second remote repository, which will track the public repository on GitHub, i.e. statnet/PKG. Let’s call it upstream.

    We do this with:

    PKG$ git remote add upstream git@github.com:statnet/PKG.git

    To verify, use git remote -v again; we should see something like:

    PKG$ git remote -v
    origin  git@github.com:statnet/PKG.git (fetch)
    origin  git@github.com:statnet/PKG.git (push)
    upstream    git@github.com:statnet/PKG.git (fetch)
    upstream    git@github.com:statnet/PKG.git (push)

4.2 Updating local repository

Fetch updates from remote repositories with

PKG$ git remote update
Fetching origin
Fetching upstream

This will fetch commits from both remote repositories (it does not do any merging, just fetching). To pull (fetch and merge) from all repositories, use

PKG$ git pull --all
Fetching origin
Fetching upstream
Already up to date.

Because the private repository is a superset of the public repository, this pull should not create any conflicts (as long as there are no commits to the local repository that have not been pushed).

4.3 Formulating commit messages

Since these two repositories have separate numberings for issues, when referencing issues in commit messages, repository name must be specified. For example, * “Fixes statnet/PKG#314.” will close the issue #314 in the public repository. * “Fixes statnet/PKG-private#314.” will close the (probably unrelated) issue #314 in the private repository. * “Fixes #314.” may have unpredictable effects.

4.4 Pushing commits (private)

A branch only found in the private repository can be pushed to simply using

PKG$ git push origin REFSPEC

All tracked branches in the private repository can be pushed via

PKG$ git push origin --all

and all tags via

PKG$ git push origin --tags

4.5 Pushing commits (public)

A branch found in both the public and the private repository (e.g., master) must be pushed to both. Before doing so, it is important to pull from both repositories and reconcile all conflicts, so that what is then pushed to both is identical.

PKG$ git checkout master
PKG$ git pull origin master; git pull upstream master
...
PKG$ git push origin master; git push upstream master

This will ensure that the two repositories remain in sync.