Gerrit Guide

Overview of Git and Gerrit

Git is an opensource distributed version control system (dvcs) written in the C language and originally developed by Linus Torvalds and others to manage the Linux kernel. In Git, there is no central copy of the repository. After you have cloned the repository, you have a functioning copy of the source code with all the branches and tagged releases, in your local repository.

Gerrit is an opensource web-based collaborative code review tool that integrates with Git. It was developed at Google by Shawn Pearce. Gerrit provides a framework for reviewing code commits before they are accepted into the code base. Changes can be uploaded to Gerrit by any user. However, the changes are not made a part of the project until a code review is completed. Gerrit is also a good collaboration tool for storing the conversations that occur around the code commits.

The OpenDaylight source code is hosted in a repository in Git. Developers must use Gerrit to commit code to the OpenDaylight repository.

Note

For more information on Git, see http://git-scm.com/. For more information on Gerrit, see https://code.google.com/p/gerrit/.

Prerequisites

Before you get started, you should have:

Setting up Each Git Repository

To clone a new repository:

git clone https://git.opendaylight.org/gerrit/${project_short_name}

For example to clone the Documentation repository:

git clone https://git.opendaylight.org/gerrit/docs

Common Gerrit Tasks

The following sections describe the most common Gerrit tasks you will need to complete while working with code in OpenDaylight.

Submitting a New Patch

  1. On your machine, open a shell and switch to the directory with the git repository. Assuming you are using the docs repository:

    cd docs
    
  2. To remove any dependencies on other files you are working on, check out the appropriate branch:

    git checkout ${remote_branch_name}  # will switch to the branch
    

    Note

    normally, ${remote_branch_name} should be master, but during a release, the master will switch to stable/${release_name}, e.g., stable/carbon at some point. Also, if you are updating an existing release check out that branch.

    Note

    If you see an error like``error: pathspec ‘stable/carbon’ did not match any file(s) known to git.``, try this command instead:

    git checkout -b ${remote_branch_name} origin/${remote_branch_name}
    

    Note

    This should only be necessary once.

  3. Get a copy of the latest files from the server:

    git pull                                      # will get all the changes from the server
    git reset --hard origin/${remote_branch_name} # (optional) will undo any local changes you've
                                                  # (accidentally) made to ${remote_branch_name}
    
  4. Create a new branch for your work:

    git checkout -b ${local_branch_name}
    

    Note

    Spaces are not allowed in ${local_branch_name}.

  5. Create new files or edit existing files, as needed.

  6. Commit the files you have worked on:

    • If you’ve created any new files, run:

      git add ${filename}
      
    • To commit existing files you edited, run:

      • git commit -as

      • Your default terminal text editor will open.

        Note

        The -as options instruct git to commit all of the files you have edited (-a) and sign your commit request with your email address and name (-s). The sign-off is to indicate that you agree with this statement:

        Developer's Certificate of Origin 1.1
        
           By making a contribution to this project, I certify that:
        
           (a) The contribution was created in whole or in part by me and I
               have the right to submit it under the open source license
               indicated in the file; or
        
           (b) The contribution is based upon previous work that, to the best
               of my knowledge, is covered under an appropriate open source
               license and I have the right under that license to submit that
               work with modifications, whether created in whole or in part
               by me, under the same open source license (unless I am
               permitted to submit under a different license), as indicated
               in the file; or
        
           (c) The contribution was provided directly to me by some other
               person who certified (a), (b) or (c) and I have not modified
               it.
        
           (d) I understand and agree that this project and the contribution
               are public and that a record of the contribution (including all
               personal information I submit with it, including my sign-off) is
               maintained indefinitely and may be redistributed consistent with
               this project or the open source license(s) involved.
        
    • Add a brief description of the changes you have made to the beginning of the commit request and then save the request.

      Note

      Writing good git commit messages is important and relatively easy, but it’s good to familiarize yourself with general guidelines like this How to Write a Git Commit Message Guide.

      Important

      We have linters that check for some of the style guides including that the first line of a git commit message is 50 characters or less. So, make sure to follow that one.

  7. Submit your files for review:

    • git review
    • You will receive 2 emails from Gerrit Code Review: The first indicating that a build to incorporate your changes has started; and the second indicating whether the build was created successfully.
  8. Determine your patch’s change number:

    • Open either of the emails you received after submitting your files for review.

    • Locate the following line in the terminal: To view, visit <patch URL>

      Note

      The number at the end of this URL is your patch’s change number. You will need this in order to make updates to the patch later.

Updating an Existing Patch

  1. On your machine, open a shell and switch to the directory containing the repository: cd ${repository_name}, e.g., cd docs

  2. Download the patch you want to update: git review -d ${change_number}

  3. (Optional) View information on the latest changes made to that patch:
    To view the files that were edited, run git show
    To view a listing of the files that were edited and the number of lines in those files that were edited, run git show --stat
  4. Make the necessary changes to the patch’s files.

  5. Commit your changes:

    1. run git commit -a --amend

    2. Update the current patch description and then save the commit request.

      Note

      If you feel as though you did enough additional work on the patch that you should be mentioned, add your name in the footer with a line like Co-Authored-By: First Last <email>.

  6. Submit your files for review:
    git review

You will receive 2 emails from Gerrit Code Review: the first indicating that a build to incorporate your changes has started; and the second indicating whether the build was created successfully.

Code Review

All contributions to OpenDaylight Git repositories use Gerrit for code review.

The code review process is meant to provide constructive feedback about a proposed change. Committers and interested contributors will review the change, give their feedback, propose revisions and work with the change author through iterations of the patch until it’s ready to be merged.

Feedback is provided and the change is managed via the Gerrit web UI.

_images/gerrit-web-ui.png

Wide view of a change via the Gerrit web UI

Pre-review

Many times, change authors will want to push changes to Gerrit before they are actually ready for review. This is a good practice and is encouraged. It has been the experience of Integration/* so far that pushing early and often tends to reduce the amount of work overall.

Note

This is not required and in some projects, not encouraged, but the general idea of making sure patches are ready for review when submitted is a good one.

Note

While in draft state, Gerrit triggers, e.g., verify Jenkins jobs, won’t run by default. You can trigger them despite it being a draft by adding jenkins-releng as a reviewer. You may need to do a recheck by replying with a comment containing recheck to trigger the jobs after adding the reviewer.

To mark an uploaded change as not ready for attention by committers and interested contributors (in order of preference), either mark the Gerrit a draft (by adding a -D to your git review command), vote -1 on it yourself or modify the commit message with “WIP” (“Work in Progress”).

Don’t add committers to the Reviewers list for a change while it’s in the pre-review state, as it adds noise to their review queue.

Review

Once an author wants a change to be reviewed, they need to take some actions to put it on the radar of the committers.

If the change is marked as a draft, you’ll need to publish it. This can be done from the Gerrit web UI.

_images/gerrit-publish-button.png

Gerrit Web UI button to publish a draft change.

Remove your -1 vote if you’ve marked it with one. If you think the patch is ready to be merged, vote +1. If there isn’t an automated job to test your change and vote +1/-1 for Verified, you’ll need to do as much testing yourself as possible and then manually vote +1 to Verified. You can also vote +1 for Verified if you’ve done testing in addition to any automated tests. Describing the testing you did or didn’t do is typically helpful.

_images/gerrit-voting-interface.png

Gerrit voting interface, exposed by the Reply button.

Once the change is published and you’ve voted for it to be merged, add the people who need to review/merge the change to the Gerrit Reviewers list. For Integration/Packaging, add all of our committers (Daniel Farrell, Jamo Luhrsen, Thanh Ha) in addition to any other relevant contributors. The auto-complete for this Gerrit UI field is somewhat flaky, but typing the full name from the start typically works.

_images/gerrit-reviewers-interface.png

Gerrit Reviewers list with Int/Pack committers added

Reviewers will give feedback via Gerrit comments or inline against the diff.

_images/gerrit-inline-feedback.png

Gerrit inline feedback about a typo

Updated versions of the proposed change should be pushed as new patchesets to the same Gerrit, either by the original submitter or other contributors. Amending proposed changes owned by others while reviewing may be more efficient than documenting the problem, -1ing, waiting for the original submitter to make the changes, re-reviewing and merging.

Changes can be downloaded for local manipulation and then re-uploaded with updates via git-review. See Updating an Existing Patch above. Once you have re-uploaded the patch the Gerrit web UI for the proposed change will reflect the new patcheset.

_images/gerrit-patch-update-history.png

Gerrit history showing a patch update

Reviewers will use the diff between the last time time they gave review and the current patchset to quickly understand updates, speeding the code review process.

_images/gerrit-diff-menu.png

Gerrit diff menu

Iterative feedback continues until consensus is reached (typically: all active reviewers +1/+2 and no -1s, definitely no -2s), at least one committer +2s and a committer merges the change.

_images/gerrit-code-review-votes.png

Gerrit code review votes

Merge

Once a patch has gotten a +2 from a committer and they have clicked the submit button the project’s merge job should run and publish the project’s artifacts to Nexus. Once this is done other projects will be able to see the results of that patch.

This is particularly important when merging dependent patches across multiple projects. You will need to wait for the merge job to run on one patch before any patches in other projects depending on it will successful verify.

Setting up Gerrit

Creating an OpenDaylight Account

  1. Using a Google Chrome or Mozilla Firefox browser, go to https://git.opendaylight.org/gerrit

    The main page shows existing Gerrit requests. These are patches that have been pushed to the repository and not yet verified, reviewed, and merged.

    Note

    If you already have an OpenDaylight account, you can click Sign In in the top right corner of the page and follow the instructions to enter the OpenDaylight page.

    Signing in to OpenDaylight account

    Signing in to OpenDaylight account

  2. If you do not have an existing OpenDaylight account, click Account signup/management on the top bar of the main Gerrit page.

    The WS02 Identity Server page is displayed.

    Gerrit Account signup/management link

    Gerrit Account signup/management link

  3. In the WS02 Identity Server page, click Sign-up in the left pane.

    There is also an option to authenticate your sign in with OpenID. This option is not described in this document.

    Sign-up link for Gerrit account

    Sign-up link for Gerrit account

  4. Click on the Sign-up with User Name/Password image on the right pane to continue to the actual sign-up page.

    Sign-up with User Name/Password Image

    Sign-up with User Name/Password Image

  5. Fill out the details in the account creation form and then click Submit.

    Filling out the details

    Filling out the details

You now have an OpenDaylight account that can be used with Gerrit to pull the OpenDaylight code.

Generating SSH keys for your system

You must have SSH keys for your system to register with your Gerrit account. The method for generating SSH keys is different for different types of operating systems.

The key you register with Gerrit must be identical to the one you will use later to pull or edit the code. For example, if you have a development VM which has a different UID login and keygen than that of your laptop, the SSH key you generate for the VM is different from the laptop. If you register the SSH key generated on your VM with Gerrit and do not reuse it on your laptop when using Git on the laptop, the pull fails.

Note

For more information on SSH keys for Ubuntu, see https://help.ubuntu.com/community/SSH/OpenSSH/Keys. For generating SSH keys for Windows, see https://help.github.com/articles/generating-ssh-keys.

For a system running Ubuntu operating system, follow the steps below:

  1. Run the following command:

    mkdir ~/.ssh
    chmod 700 ~/.ssh
    ssh-keygen -t rsa
    
  2. You are prompted for a location to save the keys, and a passphrase for the keys.

    This passphrase protects your private key while it is stored on the hard drive. You must use the passphrase to use the keys every time you need to login to a key-based system:

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/b/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /home/b/.ssh/id_rsa.
    Your public key has been saved in /home/b/.ssh/id_rsa.pub.
    

Your public key is now available as .ssh/id_rsa.pub in your home folder.

Registering your SSH key with Gerrit

  1. Using a Google Chrome or Mozilla Firefox browser, go to https://git.opendaylight.org/gerrit.

  2. Click Sign In to access the OpenDaylight repository.

    Signin in to OpenDaylight repository

    Signin in to OpenDaylight repository

  3. Click your name in the top right corner of the window and then click Settings.

    The Settings page is displayed.

    Settings page for your Gerrit account

    Settings page for your Gerrit account

  4. Click SSH Public Keys under Settings.

  5. Click Add Key.

  6. In the Add SSH Public Key text box, paste the contents of your id_rsa.pub file and then click Add.

    Adding your SSH key

    Adding your SSH key

To verify your SSH key is working correctly, try using an SSH client to connect to Gerrit’s SSHD port:

$ ssh -p 29418 <sshusername>@git.opendaylight.org
Enter passphrase for key '/home/cisco/.ssh/id_rsa':
****    Welcome to Gerrit Code Review    ****
Hi <user>, you have successfully connected over SSH.
Unfortunately, interactive shells are disabled.
To clone a hosted Git repository, use: git clone ssh://<user>@git.opendaylight.org:29418/REPOSITORY_NAME.git
Connection to git.opendaylight.org closed.

You can now proceed to either Pulling, Hacking, and Pushing the Code from the CLI or Pulling, Hacking, and Pushing the Code from Eclipse depending on your implementation.

Using https to push to Gerrit

It is highly recommended to use ssh to push to Gerrit. In the event that you cannot use ssh, e.g., a corporate firewall is blocking blocking you, then falling back to pushing via https should work.

Gerrit does not allow you to use your regular account credentials when pushing via https. Instead it requires you to first generate a http password via the Gerrit Web UI and use that as the password when pushing via https.

_images/gerrit-https-password-setup.png

Setting up an https password to push using https instead of ssh.

To do this:

  1. navigate to https://git.opendaylight.org/gerrit/#/settings/http-password (Steps 1, 2 and 3 in the image above.)
  2. click the Generate Password button.

Gerrit will then generate a random password which you will need to use as your password when using Git to push code to Gerrit via https.

To push using git over https, do the following

git remote add https https://git.opendaylight.org/gerrit/p/${repo_name}  # adds an https version of the git server
git push https HEAD:refs/for/${branch_name}                        # will ask you for your username and password
                                                                   #   ${branch_name} should usually be master,
                                                                   #   but can be stable/carbon or something else

Signing Gerrit Commits

  1. Generate your GPG key.

    The following instructions work on a Mac, but the general approach should be the same on other OSes.

    brew install gpg2  # If you don't have homebrew, get that here: http://brew.sh/
    gpg2 --gen-key
    # pick 1 for "RSA and RSA"
    # enter 4096 to creat a 4096-bit key
    # enter an expiration time, I picked 2y for 2 years
    # enter y to accept the expiration time
    # pick O or Q to accept your name/email/comment
    # enter a pass phrase twice. it seems like backspace doesn't work, so type carefully
    gpg2 --fingerprint
    # you'll get something like this:
    # spectre:~ ckd$ gpg2 --fingerprint
    # /Users/ckd/.gnupg/pubring.gpg
    # -----------------------------
    # pub   4096R/F566C9B1 2015-04-06 [expires: 2017-04-05]
    #       Key fingerprint = 7C37 02AC D651 1FA7 9209  48D3 5DD5 0C4B F566 C9B1
    # uid       [ultimate] Colin Dixon <colin at colindixon.com>
    # sub   4096R/DC1497E1 2015-04-06 [expires: 2017-04-05]
    # you're looking for the part after 4096R, which is your key ID
    gpg2 --send-keys $KEY_ID
    # in the above example, the $KEY_ID would be F566C9B1
    # you should see output like this:
    # gpg: sending key F566C9B1 to hkp server keys.gnupg.net
    

    If you’re trying to participate in an OpenDaylight keysigning, then send the output of gpg2 --fingerprint $KEY_ID to keysigning@opendaylight.org

    gpg2 --fingerprint $KEY_ID
    # in the above example, the $KEY_ID would be F566C9B1
    # in my case, the output was:
    # pub   4096R/F566C9B1 2015-04-06 [expires: 2017-04-05]
    #       Key fingerprint = 7C37 02AC D651 1FA7 9209  48D3 5DD5 0C4B F566 C9B1
    # uid       [ultimate] Colin Dixon <colin at colindixon.com>
    # sub   4096R/DC1497E1 2015-04-06 [expires: 2017-04-05]
    
  2. Install gpg, instead of or addition to gpg2. It appears as though gpg2 has annoying things that it does when asking for your passphrase, which I haven’t debugged yet.

    Note

    you can tell Git to use gpg by doing: git config --global gpg.program gpg2 but that then will seem to struggle asking for your passphrase unless you have your gpg-agent set up right.

  3. Add you GPG to Gerrit

    1. Run the following at the CLI:

      gpg --export -a $FINGER_PRINT
      # e.g., gpg --export -a F566C9B1
      # in my case the output looked like:
      # -----BEGIN PGP PUBLIC KEY BLOCK-----
      # Version: GnuPG v2
      #
      # mQINBFUisGABEAC/DkcjNUhxQkRLdfbfdlq9NlfDusWri0cXLVz4YN1cTUTF5HiW
      # ...
      # gJT+FwDvCGgaE+JGlmXgjv0WSd4f9cNXkgYqfb6mpji0F3TF2HXXiVPqbwJ1V3I2
      # NA+l+/koCW0aMReK
      # =A/ql
      # -----END PGP PUBLIC KEY BLOCK-----
      
    2. Browse to https://git.opendaylight.org/gerrit/#/settings/gpg-keys

    3. Click Add Key...

    4. Copy the output from the above command, paste it into the box, and click Add

  4. Set up your Git to sign commits and push signatures

    git config commit.gpgsign true
    git config push.gpgsign true
    git config user.signingkey $FINGER_PRINT
    # e.g., git config user.signingkey F566C9B1
    

    Note

    you can do this instead with git commit -S You can use git commit -S and git push --signed on the CLI instead of configuring it in config if you want to control which commits use your signature.

  5. Commit and push a change

    1. change a file

    2. git commit -asm "test commit"

      Note

      this should result in Git asking you for your passphrase

    3. git review

      Note

      this should result in Git asking you for your passphrase

      Note

      annoyingly, the presence of a gpgp signature or pushing of a gpg signature isn’t recognized as a “change” by Gerrit, so if you forget to do either, you need to change something about the commit to get Gerrit to accept the patch again. Slightly tweaking the commit message is a good way.

      Note

      this assumes you have git review set up and push.gpgsign set to true. Otherwise:

      git push --signed gerrit HEAD:refs/for/master

      Note

      this assumes you have your gerrit remote set up, if not it’s something like: ssh://ckd@git.opendaylight.org:29418/<repo>.git where repo is something like docs or controller

  6. Verify that your commit is signed by going to the change in Gerrit and checking for a green check (instead of a blue ?) next to your name.

Setting up gpg-agent on a Mac

  1. Install gpg-agent and pinentry-mac using brew:

    brew install gpg-agent pinentry-mac
    
  2. Edit your ~/.gnupg/gpg.conf contain the line:

    use-agent
    
  3. Edit your ~/.gnupg/gpg-agent.conf to something like:

    use-standard-socket
    enable-ssh-support
    default-cache-ttl 600
    max-cache-ttl 7200
    pinentry-program /usr/local/bin/pinentry-mac
    
  4. Edit your .bash_profile or equivalent file to contain the following:

    [ -f ~/.gpg-agent-info ] && source ~/.gpg-agent-info
    if [ -S "${GPG_AGENT_INFO%%:*}" ]; then
      export GPG_AGENT_INFO
    else
      eval $( gpg-agent --daemon --write-env-file ~/.gpg-agent-info )
    fi
    
  5. Kill any stray gpg-agent daemons running:

    sudo killall gpg-agent
    
  6. Restart your terminal (or log in and out) to reload the your .bash_profile or equivalent file

  7. The next time a Git operation makes a call to gpg, it should use your gpg-agent to run a GUI window to ask for your passphrase and give you an option to save your passphrase in the keychain.

    _images/pinentry-mac.png