Skip to content

Git workflow

Olivier Michel edited this page Sep 30, 2019 · 24 revisions

Setting up your identity

You need to setup your identity so that your pushes are correctly identified and appear under your name on github:

git config --global user.email "[email protected]"
git config --global user.name "Billy Everyteen"

additionally you can cache your username and password so that you don't have to type them every time you contact github:

git config --global credential.helper cache

More information about set up git can be found at https://help.github.com/articles/set-up-git.

Adopted branching model

http://nvie.com/posts/a-successful-git-branching-model/

The git tagging system allows to freeze efficiently instant where to create packages (and release candidate to test).

Every commit to the develop, revision or master branch should be done through a moderated Pull Request.

Here is what can be committed to the different branches:

  • develop may receive new features, any change that breaks the binary compatibility and large code refactoring.
  • revision may receive bug fixes, optimizations, clean-up.
  • master may receive only documentation improvements that refer to the current release and which will be immediately published on Cyberbotics's web site as soon as they are merged.

Branch naming

New branches should be named according to the following syntax: <prefix>-<subject> where prefix should be one the following:

hotfix: for a urgent enhancement/fix/doc/feature fix
fix: for a bug fix
doc: for a new documentation work
feature: for a new feature
enhancement: not a fix nor a feature (typically a code refactor)
update: for an update (cache files or release version for example)
cleanup: for removing unused files, comments, etc.

and subject should describe the issue explicitly, e.g., avoid subjects like "issue-89". It should be composed only of lowercase alphabetical characters, digits and dash signs (-) to separate worlds. The corresponding pull request should keep the same name as the branch. Examples of branch names:

hotfix-add-missing-texture-in-nao-appartment
fix-touch-sensors-without-physics-fail-with-ode-mt
doc-new-ros-tutorial
feature-procedural-protos

Regular workflow

# setup the git repository
cd ~/develop
git clone https://github.com/cyberbotics/webots.git
cd webots
git submodule init

while (workingOnWebots) {
  if (hotfix) {
    # Bug fixes, optimizations, clean-up
    # Enter in the revision branch
    git checkout revision

    # Update the revision branch
    git fetch origin
    git merge origin/revision [revision]

    git submodule update
  } else {
    # New features, changes breaking binary compatibility, code refactoring, etc.
    # Enter in the develop branch
    git checkout develop

    # Update the develop branch
    git fetch origin
    git merge origin/develop [develop]

    git submodule update
  }

  # Create a new feature branch
  git checkout -b <my-new-feature>

  # verify the branches list
  if (required)
    git branch

  # modify and commit files
  while (required) {

    while (required) {
      -> modify files
      git diff [<modified-files>]
      git status
    }

    # added files to the stage
    git add [<modified-files>]

    # monitor the already committed files
    if (required)
      git diff --staged [<modified-files>]

    # commit files
    # note: commits are local
    git commit [<modified-files>] -m "<My detailed comment>"

    # push the branch on the remote repository if required
    if (someTimes or lastCommit) {
      git push origin <my-new-feature>

      -> Look through the modifications in the GitHub GUI
    }

    # Create the Pull Request (PR)
    # this is can be done at an early development stage in order to open the
    # discussion with the colleagues, share a todo list and/or a description
    # of the aims. In such a case, the PR should be opened as a draft PR.
    if (someTimes or lastCommit) {
      -> From the GitHub GUI: find the "Compare and Pull Request" button
      if (hotfix)
        put origin/<my-new-feature> into origin/revision
      else
        put origin/<my-new-feature> into origin/develop    
    }

    if (lastCommit) {
      -> If the github "Merge" button is unavailable because GitHub detected
         a merge conflict, the developer should fix it:
      if (mergeButtonDisabled)
        continue
      -> The developer should check by how many commits her branch is behind the
         develop (displayed as "behind" on the GitHub branches page) and evaluate
         the risk of bugs arising from possible logic conflicts (as opposed to merge
         conflicts which are well managed by GitHub ).
      if (developerUnsureAboutPossibleLogicConflict) {
        -> The developer should merge the current develop with her branch:
        git merge origin/develop
        git push origin <my-new-feature>
        -> and test her code again, if the test fails, she should fix the problems.
        if (testFail)
          continue
      }

      if (webotsSourceCodeIsModified) {
        -> Run a Jenkins test
        if (testFail)
          continue
      }

      if (importantChanges) {
        launch a Travis unit test manually from https://travis-ci.com:
        - More options -> Trigger build -> Select branch -> Type "travis_unit" in
          the CUSTOM COMMIT MESSAGE field.
      }

      -> The developer can thumb up (":+1:") himself the PR to indicate to her
         colleagues the PR is complete and ready for review.
      -> If a travis_unit test was launched, the developer should add a ✔️
         ":heavy_check_mark:" next to the thumb up 👍 to mean that the unit_test
         passed successfully. 
      -> The reviewer has to post a review icon (":eyes:") when he starts the review
         (to avoid that multiple developers review at the same time).
      -> Then, she can review the PR and comment or thumb up.
      -> When the last comments include 2 thumb up (":+1:") and without any other text
         except for review icons, then, the PR can be merged.
      -> Alternatively, if the developer needs a specific reviewer or more than one
         reviewer, she can add this information after the thumb up, e.g.,
         :+1: 2 -> means "I need that two people review this critical PR"
         :+1: @omichel -> means "I need that @omichel review this PR as he is
              knowledgeable on this topic"
         :+1: @fabienrohrer + 1 -> means "I need that @fabienrohrer and 1 other
              developer review this PR"
         In such cases, 3 or more thumbs are needed so that the PR can be merged.
      if (the PR can be merged) {
        # The developer has the responsibility to accept/delete the remote/local
          branches
        # The developer accepts the PR from the GitHub GUI

        if (hotfix) {
          # update develop branch
          -> open a new PR from GitHub GUI (green button in 'Code' or
             'Pull Request' page) to merge origin/revision into origin/develop
          -> set 'base' to 'develop' and 'compare' to 'revision' before pressing
             the 'Create Pull Request' button
          if (mergeButtonDisabled) {
            -> The developer has to close or abort the creation of this second PR
            -> create a new branch <merge-revision-into-develop> based on the
               'develop' branch
            -> merge with origin/develop and fix conflicts
            -> create a PR that merges into 'develop'
          }

          -> The developer has to thumb up (":+1:") to ask her colleagues for a
             review
          -> The reviewer has to comment or thumb up (":+1:") the PR
          -> Once two consecutive thumb up (":+1:") are issued, the develop can
             merge the PR

          if (newBranchWasCreated)
            -> The developer has to close and delete the
               <merge-revision-into-develop> branch
        }

        if (wantToDelete) {
          # delete the remote branch (GitHub has also a button in the PR to do that)
          git push origin :<my-new-feature>

          # Delete the the local branch
          git checkout develop
          git branch -d <my-new-feature> # use '-D' instead of '-d' to delete an
                                         # un-merged branch
          break
        }
      }
      else { // not accepted
        The reviewer should explain what's wrong with the PR
      }
    }
  }
}

submodules

doc is a submodule (git repository webots-doc) projects/robots/aldebaran is a submodule (git repository cyberbotics/aldebaran) etc.

These directory behave as a standalone git repository with their own branching/commit/push/etc. system.

doc or projects/robots/aldebaran can be see as a file containing the commit on which the checkout has to be done. Once synchronized, it behaves transparently.

When working on a pull request (PR) on the webots repository, one might need to change the contents of some submodules, such as the doc submodule. In that case, a PR for each submodule should be open, with the same branch name as the webots PR and the same target branch as the webots PR (master, revision or develop). When the review of all the PRs is complete (including the webots PR and its sub-PRs), the developer should first merge the sub-PRs. Then, he should synchronize the webots PR with the merged sub-PRs (e.g., for the doc submodule: cd doc ; git checkout master ; git fetch ; git pull ; cd .. ; git add doc ; git commit -m"sync with doc submodule master") before merging the webots PR.

Release workflow

Current release

The master branch should always be ready to create a distribution of the current release, with a possibly improved documentation.

Revision release

The revision branch should always be ready to create a distribution of the current revision. When all the issues referring to the revision milestone are closed (or moved to another milestone), a new PR should be open to merge the revision branch into the master branch. The PR should contain a tick-box list for all the test needed before a release can be published, e.g, change log update, QA tests and test suite for all platforms. Once this PR is accepted, the release is published and the revision branch is merged in the master branch.

Major release

The develop branch should always contain a stable version of the upcoming major release of Webots. When all the issues referring to a major release milestone are closed (or moved to another milestone), a new PR should be open to merge the develop branch into the master branch. The PR should contain a tick-box list for all the test needed before a release can be published, e.g, change log update, QA tests and test suite for all platforms. Once this PR is accepted, the release is published and the develop branch is merged in the master branch.

Misc useful git tricks

Branch with multiple developers

Get locally an existing remote branch:

git fetch origin
git branch <her-new-branch> origin/<his-new-branch>
git checkout <her-new-branch>
-> apply the regular workflow

Switch between branches

It is highly recommended to commit (even simply locally) the changes before switching branches. Otherwise a conflict has to be managed (the conflict is simply that the uncommitted files are also present to the target branch)

# list the branches
git branch
# switch
git checkout <expected-branch>

More information there: http://www.gitguys.com/topics/switching-branches-without-committing/

Git ignore

Ignoring files is managed by adding .gitignore files.

# .gitignore file

# rule applied recursively
*.o

# rule applied locally
/*.class

# exception breaking the recursion
!foo.o

Complete documentation: http://git-scm.com/docs/gitignore

Revert a commit

# to get the commit id, either look at the PR commits, or type
git log

git revert dd61ab32
# if the commit is on the remote, then the next push will revert it:
git push origin <my-feature>

Prune your local fork

When a branch is deleted in remote (typically after deleting a branch from GitHub), a stale branch can stay locally. This can be annoying when auto-completing, and using git branch -a. The following command allows to clean your local directory.

git remote prune origin

Using regularly the -p argument when fetching the remote repository allows to avoid this issue:

git fetch -p

Create a release tag

git tag -a vX.Y.Z -m "Webots X.Y.Z"
git push origin vX.Y.Z
Clone this wiki locally