Skip to content

Git workflows

Rich Wareham edited this page Oct 3, 2013 · 15 revisions

Important: A lot of ROS assumes that the various machines that are talked to have roughly the same idea of messages, services, resource files, etc, etc. We use git to keep everything synchronised between machines. It is important that a well defined workflow is used. This is particularly true since we'll be sharing the robot.

If you have not yet done so, read at least the first few chapters of the git book.

We use something akin to GitHub flow. Read about it. Also watch one of the many videos on YouTube about branching and merging in git.

Rule 0: experts break the rules

Even more important than rule 1: once you understand the system, you know when to break the rules. Until you feel confident in collaborative software development, follow these rules. But rules can be broken when you are a) an expert and b) can justify it.

Rule 1: master is always good

Everything in the master branches in our repos should be runnable. Except for rare occasions the Q.bo will only ever have the master branch checked out. (See the making local changes on Q.bo below for an exception.) If you make a change to one of the qbo_... repos, only changes in the master branch will make it onto the robot long-term.

However, never commit directly to master. Everything must end up on master either via git merge or, far preferably, via a pull request on GitHub.

Making a change on your machine

Always work on feature branches. The very first thing you should do after cloning a repository from GitHub is to create a feature branch and always branch from master. The best way to do this is to explicitly give master as the branch point in git branch.

$ git clone [email protected]:sigproc/the-repo
$ cd the-repo
$ git branch feature-branch-name master   # create branch 'feature-branch-name' from 'master'
$ git checkout feature-branch-name        # move to the branch, new commits will be on this branch

Branches are always named like-this, never likeThis, LikeThis, likethis or like this.

Developing your change

Your workflow goes like this:

  1. Make a small change which moves you towards your goal.
  2. Does it work?
  3. If yes, git commit, if no modify and go to 2.
  4. If your goal is not yet reached, go to 1.
  5. git push the branch and submit a pull-request on GitHub.

You should be running git commit early and often. A complex change can be many commits. At any time you can push your branch to GitHub as a backup/for comment:

Pushing your change

Although you will push your change as a precursor to getting it merged, there is nothing stopping you pushing your branch as often as you want. Until you create a pull request, it wont bother anyone else.

(the first time you push a branch)
$ git push -u origin feature-branch-name
(subsequently, git remembers where to push)
$ git push

When you're ready for your change to go into master, create a pull request.

Merging your change

Apart from in exceptional circumstances, you should never merge your own pull request. Get someone else to do it. This is to ensure that at least one other person's eyes have looked at the code. They may have some helpful comments to make. The corollary to this is that you should regularly look at the waiting pull requests from others and merge them if they seem sensible.

Exceptional circumstances include everyone else being away for the week or your project presentation being in five minutes time.

Sensible changes are, quite simply, ones whose purpose is clear and whose code you can understand. If you don't understand the change, comment in the pull request. There is no better way of making sure your code is of high quality than explaining it to another.

Making a local change on Q.bo

Firstly: do you really need to make the change on Q.bo first, rather than making the change on your own machine, testing it, committing it and pulling on Q.bo? Think carefully. An example of where changes must necessarily be made on the Q.bo are when files are updated on it by nodes, e.g. when calibrating the cameras.

Secondly: read how to create and apply a patch with Git.

Thirdly: the Q.bo will need to be able to access the Internet. Make sure the wired connection is plugged in.

The motivation for the indirect way we do the changes (create a branch on the Q.bo, manually transfer to your machine, push to GitHub and then pull back to the Q.bo) is that it makes sure that all changes on the Q.bo which are in master branches must be backed up on GitHub and must be annotated with who made the changes. Both of these things are important if we ever want to re-install the robot.

If you have thought carefully, and read the article above, the first thing to do is to work on a separate branch:

(on Q.bo)
$ roscd package_name
$ git branch feature-branch-name master
$ git checkout feature-branch-name

Make your changes, making sure to git commit early and often. You should then have a branch which is one or more commits ahead of master. Create a series of patches:

(on Q.bo)
$ git format-patch --stdout master >my-changes.mbox

This will print out the names of the patch file(s). Copy them to your machine:

(on your machine)
$ scp qbo:~/cued-masters/path/to/my-changes.mbox  .

Now, on your machine, create a new branch:

(on your machine)
$ roscd package_name
$ git checkout master
$ git checkout -b feature-branch-name

Apply each patch:

(on your machine)
$ git am --signoff < path/to/my-changes.mbox

The --signoff is there to add Signed-off-by tags to each commit. That way you can note that you've made the changes and think they're OK.

Now merge the branch and push as usual:

(on your machine)
$ git checkout master
$ git merge --no-ff feature-branch-name
$ git push

Finally, update the Q.bo:

(on Q.bo)
$ git checkout master
$ git pull
$ git branch -d feature-branch-name    # you may need to use '-D' and not '-d'

Only ever rebase when pulling

This is the rationale for the following magic bits of git config:

$ git config --global branch.master.rebase true
$ git config --global branch.autosetuprebase always

The default behaviour of git when your master branch differs from the origin/master branch is to do a git merge when you issue the git pull command. Most of the time this does the right thing: the remote changes are added atop your local ones. The problem comes if your local master and the origin/master branch have diverged, that is to say there are commits in master which are not in origin/master. This should not happen if you follow the workflows above but accidents happen. In this case the git merge will merge origin/master into master. This is almost always not what you want.

If anything you want to merge the other way around since origin/master is seen as the 'spine' of development.

The configuration above changes the default behaviour to splice the new commits in origin/master before the new commits in master. This matches what you'd expect git to do in the first place given our workflow.

Advanced: if you have non-SigProC git repositories on your machine, you can omit the --global argument in order to make the configuration per-repository.