Skip to content
Sean R. Eddy edited this page Jan 31, 2017 · 6 revisions

git workflow

Easel has switched to using a popular git workflow that's often just called "git flow". Go read the 2010 blog post by Vincent Driessen that describes it. We will use it with two differences:

  • How we manage having Infernal depend on HMMER, and HMMER on Easel.

  • We don't mind having feature branches on origin.

In what follows, first we'll give concise-ish examples of the flow for normal development, making a release, and making a "hotfix". A summary of the principles and rationale follows the examples.

Normal development

Generally, for any changes you make to our code, you will make on a feature branch, off of develop. So first you create your branch:

   $ git checkout -b myfeature develop            

Now you work, for however long it takes. You can make commits on your myfeature branch locally. Working with a local branch on your own machine will often be sufficient. But if you want to push your feature branch up to github (origin) -- maybe you want to be able to clone it for testing on a bunch of different platforms -- you can do that:

   $ git push -u origin myfeature

When you're done, and you've tested your new feature, you merge it to develop (using --no-ff, which makes sure a clean new commit object gets created), and delete your feature branch:

   $ git checkout develop                     
   $ git merge --no-ff myfeature
   $ git branch -d myfeature
   $ git push origin --delete myfeature
   $ git push origin develop                  

Small features: single commits can be made to develop

Alternatively, if you're sure your change is going to be a single commit, you can work directly on the develop branch.

   $ git checkout develop                  
     # make your changes
   $ git commit
   $ git push origin develop               

Big features: keeping up to date with develop

If your work on a feature is taking a long time (days, weeks...), and if the develop trunk is accumulating changes you want, you might want to periodically merge them in:

   $ git checkout myfeature
   $ git merge --no-ff develop           

Making a release

To make a release, you're going to make a release branch of the code, and of any other repos it depends on. For example, for an Infernal release, you're going to make release branches in HMMER and Easel too. You assign appropriate version numbers to each, test and stabilize. When everything is ready, you merge to master and tag that commit with the version number; then you also merge back to develop, and delete the release branch.

For example, here's the git flow for a HMMER release, depending on Easel. Suppose HMMER is currently at 3.2.1, Easel is currently at 0.2.3, and we decide this release will be HMMER 3.2.2 with Easel 0.2.4:

   $ cd easel
   $ git checkout -b release-0.2.4 develop
     # change version numbers to 0.2.4; also dates, copyrights
   $ git commit -a -m "Version number bumped to 0.2.4"

then HMMER:

   $ cd hmmer
   $ git checkout -b release-3.2.2 h3-develop
     # Change version numbers to 3.2.2; also dates, copyrights
   $ git commit -a -m "Version number bumped to 3.2.2"

Now you do your release testing, making any changes and commits you need to make. When you're done, merge to master and tag it; then merge to develop and delete the release branch. Dependencies get tagged twice, once for themselves (Easel 0.2.4) and one for the main package that's going to depend on them (HMMER 3.2.2):

   $ cd easel
   $ git checkout master
   $ git merge --no-ff release-0.2.4
   $ git tag -a 0.2.4
   $ git push origin 0.2.4
   $ git tag -a hmmer-3.2.2
   $ git push origin hmmer-3.2.2
     # this records that the hmmer 3.2.2 release depended on this Easel commit object
   $ git push
   $ git checkout develop
   $ git merge --no-ff release-0.2.4
   $ git push
   $ git branch -d release-0.2.4
   $ git push origin --delete release-0.2.4

and do the same in HMMER, for its release-3.2.2 (in the h3-master branch) tagging it just once with 3.2.2.

Using existing releases

If you don't need a new Easel release, you can use the last release on the master branch; you just have to tag it.

   $ cd easel
   $ git checkout master
   $ git tag -a hmmer-3.2.2

Fixing bugs: "hotfix" branches

If you need to fix a critical bug and make a new release immediately, you create a hotfix release with an updated version number, and the hotfix release is named accordingly: for example, if we screwed up Easel 0.2.4, hotfix-0.2.5 is the updated 0.2.5 release.

A hotfix branch comes off master, but otherwise is much like a release branch.

   $ cd easel
   $ git checkout -b hotfix-0.2.5 master                 
     # bump version number to 3.2.3; also dates, copyrights
   $ git commit -a -m "Version number bumped to 0.2.5"

Now you fix the bug(s), in one or more commits. When you're done, the finishing procedure is just like a release:

    $ git checkout master              
    $ git merge --no-ff hotfix-0.2.5
    $ git tag -a 0.2.5
    $ git checkout develop              
    $ git merge --no-ff hotfix-0.2.5
    $ git branch -d hotfix-0.2.5


Summary of main principles

There are two infinite-lifetime branches in each of our github repos (origin): origin/master, and origin/develop. All other branches have limited lifetimes.

master is stable. Every commit object on master is a tagged release, and vice versa.

develop is for ongoing development destined to be in the next release. develop should be in a close-to-release state. Another package (e.g. Infernal) may need to create a release of a downstream dependency (e.g. Easel) at short notice. Therefore, commit objects on develop are either small features in a single commit, or a merge of a finished feature branch.

We make a feature branch off develop for any nontrivial new work -- anything that you aren't sure will be a single commit on develop. A feature branch:

  • comes from develop
  • is named anything informative (except master, develop, hotfix-* or release-*)
  • is merged back to develop (and deleted) when you're done
  • is deleted once merged

We make a release branch off develop when we're making a release. A release branch:

  • comes from develop
  • is named release-<version>, such as release-3.2.2
  • first commit on the hotfix branch consists of bumping version/date/copyright
  • is merged to master when you're done, and that new commit gets tagged as a release
  • is then merged back to develop too
  • is deleted once merged

We make a hotfix branch off master for a critical immediate fix to the current release. A hotfix branch:

  • comes from master
  • is named hotfix-<version>, such as hotfix-3.2.3
  • first commit on the hotfix branch consists of bumping version/date/copyright
  • is merged back to master when you're done, and that new commit object gets tagged as a release.
  • is then merged back to develop too
  • is deleted once merged