langhuayipian / git / gerrit 配置

0 0


gerrit 配置

2013-09-16  langhuayi...

Code Review with Gerrit, a mostly visual guide published on 07 December 2009

Update: Some of this information is out of date. Instead of pushing to the gerrit master branch I recommend setting up "replication" and using the "Submit" button inside of the "Review" page.

A while ago, when Paul, Jason and I worked together, I became a big fan of code reviews before merging code. It was no surprise really, we were the first to adopt Git at the company and our workflow was quite ad-hoc, the need to federate knowledge within the group meant code reviews were a pretty big deal. At the time, we mostly did code reviews in person by way of "hey, what's this you're doing here?" or by literally sending patch emails with git-format-patch(1) to the team mailing list so all could participate in the discussion about what merits "good code" exhibited versus "less good code." Now that I've left that company and joined another one, I've found myself in another small-team situation, where my teammates place high value on code review. Fortunately this time around better tools exist, namely: Gerrit.

The history behind Gerrit I'm a bit hazy on, what I do know is that it's primary developer Shawn Pearce (spearce) is one of the Git "inner circle" who contributes heavily to Git itself as well as JGit, a Git implementation in Java which sits underneath Gerrit's internals. What makes Gerrit unique in the land of code review systems is how tightly coupled Gerrit is with Git itself, so much so that you submit changes by pushing as if the Gerrit server were "just another Git repo."

I recommend building Gerrit from source for now, spearce is planning a proper release of the recent Gerrit developments shortly before Christmas, but who has that kind of patience! To build Gerrit you will need Maven and the Sun JDK 1.6.

Setting up the Gerrit daemon

First you should clone one of Gerrit's dependencies, followed by Gerrit itself:

banana% git clone git://
banana% git clone git://

Once both clones are complete, you can start by building one and then the other (which might take a while, go grab yourself a coffee, you've earned it):

banana% (cd gwtexpui && mvn install)
banana% cd gerrit && mvn clean package

After Gerrit has finished building, you'll have a .war file ready to run Gerrit with (note: depending on when you read this article, your path to gerrit.war might have changed). First we'll initialize the directory "/srv/gerrit" as the location where the executing Gerrit daemon will store its logs, data, etc:

banana% java -jar gerrit-war/target/gerrit-2.0.25-SNAPSHOT.war init -d /srv/gerrit
*** Gerrit Code Review v2.0.24.2-72-g4c37167

Initialize '/srv/gerrit' [y/n]? y

*** Git Repositories

Location of Git repositories   [git]:

*** SQL Database

Database server type           [H2/?]:

*** User Authentication

Authentication method          [OPENID/?]:

*** Email Delivery

SMTP server hostname           [localhost]:
SMTP server port               [(default)]:
SMTP encryption                [NONE/?]:
SMTP username                  :

*** SSH Daemon

Gerrit SSH listens on address  [*]:
Gerrit SSH listens on port     [29418]:

Gerrit Code Review is not shipped with Bouncy Castle Crypto v144
  If available, Gerrit can take advantage of features
  in the library, but will also function without it.
Download and install it now [y/n]? y
Downloading ... OK
Checksum bcprov-jdk16-144.jar OK
Generating SSH host key ... rsa... dsa... done

*** HTTP Daemon

Behind reverse HTTP proxy (e.g. Apache mod_proxy) [y/n]? n
Use https:// (SSL)             [y/n]? n
Gerrit HTTP listens on address [*]:
Gerrit HTTP listens on port    [8080]: 

Initialized /srv/gerrit

After running through Gerrit's brief wizard, you'll be ready to start Gerrit itself (note: this command will not detach from the terminal, so you might want to start it within screen for now):

banana% java -jar gerrit-war/target/gerrit-2.0.25-SNAPSHOT.war daemon -d /srv/gerrit

Now that you've reached this point you'll have Gerrit running a web application on port 8080, and listening for SSH connections on port 29418, congratulations! You're most of the way there :)

Creating users and groups

Welcome to Gerrit

First thing you should do after starting Gerrit up is log in to make sure your user is the administrator, you can do so by clicking the "Register" link in the top right corner which should present you with an openID login dialog

After logging in with your favorite openID provider, Gerrit will allow you to enter in information about you (SSH key, email address, etc). It's worth noting that the email address is very important as Gerrit uses the email address to match your commits to your Gerrit account

When you create your SSH key for Gerrit, it's recommended that you give it a custom entry in ~/.ssh/config along the lines of:

Host gerrithost
    User <you>
    Port 29418
    Hostname <gerrithost>
    IdentityFile <path/to/private/key>

After you click "Continue" at the bottom of the user information page, you will be taken to your dashboard which is where your changes waiting to be reviewed as well as changes waiting to be reviewed by you will be waiting

Now that your account is all set up, let's create a group for "integrators", integrators in Git parlance are those that are responsible for reviewing code and integrating it into the "official" repository (typically integrators are project maintainers or core developers). Be sure to add yourself to the "Integrators" group, we'll use this "Integrators" group later to create more granular permissions on a particular project:

Projects in Gerrit

Creating a new project in Gerrit is fairly easy but a little different insofar that there isn't a web UI for doing so but there is a command line one:

banana% ssh gerrithost gerrit create-project -n <project-name>

For the purposes of my examples moving forward, we'll use a project created in Gerrit for one of the Python modules I maintain, py-yajl. After creating the "py-yajl" project with the command line, I can visit Admin > Projects and select "py-yajl" and edited some of its permissions. Here we'll give "Integrators" the ability to Verify changes as well as Push Branch.

With the py-yajl project all set up in Gerrit, I can return to my Git repository and add a "remote" for Gerrit, and push my master branch to it

banana% git checkout master
banana% git remote add gerritrhost ssh://gerrithost/py-yajl.git
banana% git push gerrithost master

This will give Gerrit a baseline for reviewing changes against and allow it to determine when a change has been merged down. Before getting down to business and starting to commit changes, it's recommended that you install the Gerrit Change-Id commit-msg hook documented here which will help Gerrit track changes through rebasing; once that's taken care of, have at it!

banana% git checkout -b topic-branch
banana% <work>
banana% git commit 
banana% git push gerrithost HEAD:refs/for/master

The last command will push my commit to Gerrit, the command is kind of weird looking so feel free to put it behind a git-alias(1). After the push is complete however, my changes will be awaiting review in Gerrit

At this point, you'd likely wait for another reviewer to come along and either comment your code inline in the side-by-side viewer or otherwise approve the commit bu clicking "Publish Comments"

After comments have been published, the view in My Dashboard has changed to indicate that the change has not only been reviewed but also verified:

Upon seeing this, I can return back to my Git repository and feel comfortable merging my code to the master branch:

banana% git checkout master
banana% git merge topic-branch
banana% git push origin master
banana% git push gerrithost master

The last command is significant again, by pushing the updated master branch to Gerrit, we indicate that the change has been merged, which is also reflected in My Dashboard

Tada! You've just had your code reviewed and subsequently integrated into the upstream tree, pat yourself on the back. It's worth noting that while Gerrit is under steady development it is being used by the likes of the Android team, JGit/EGit team and countless others. Gerrit contains a number of nice subtle features, like double-clicking a line inside the side-by-side diff to add a comment to that line specifically, the ability to "star" changes (similar to bookmarking) and a too many others to go into detail in this post.

While it may seem like this was a fair amount of set-up to get code reviews going, the payoff can be tremendous, Gerrit facilitates a solid Git-oriented code review process that scales very well with the number of committers and changes. I hope you enjoy it :)


Gerrit supports three methods of uploading changes:

  • Use repo upload, to create changes for review

  • Use git push, to create changes for review

  • Use git push, and bypass code review

All three methods rely on SSH public key authentication, which must first be configured by the uploading user.


Each user uploading changes to Gerrit must configure one or more SSH public keys. The per-user SSH key list can be accessed over the web within Gerrit by Settings, and then accessing the SSH Public Keys tab.


To register a new SSH key for use with Gerrit, paste the contents of your or file into the text box and click the add button. Gerrit only understands SSH version 2 public keys. Keys may be supplied in either the OpenSSH format (key starts with ssh-rsa or ssh-dss) or the RFC 4716 format (file starts with ---- BEGIN SSH2 PUBLIC KEY ----).

Typically SSH keys are stored in your home directory, under ~/.ssh. If you don’t have any keys yet, you can create a new one and protect it with a passphrase:

ssh-keygen -t rsa

Then copy the content of the public key file onto your clipboard, and paste it into Gerrit’s web interface:

cat ~/.ssh/
Users who frequently upload changes will also want to consider starting an ssh-agent, and adding their private key to the list managed by the agent, to reduce the frequency of entering the key’s passphrase. Consult man ssh-agent, or your SSH client’s documentation, for more details on configuration of the agent process and how to add the private key.

Testing Connections

To verify your SSH key is working correctly, try using an SSH client to connect to Gerrit’s SSHD port. By default Gerrit runs on port 29418, using the same hostname as the web server:

  $ ssh -p 29418 sshusername@hostname

    ****    Welcome to Gerrit Code Review    ****

    Hi John Doe, you have successfully connected over SSH.

    Unfortunately, interactive shells are disabled.
    To clone a hosted Git repository, use:

    git clone ssh://sshusername@hostname:29418/REPOSITORY_NAME.git

  Connection to hostname closed.

In the command above, sshusername was configured as Username on the Profile tab of the Settings screen. If it is not set, propose a name and use Select Username to select the name.

To determine the port number Gerrit is running on, visit the special information URL http://'hostname'/ssh_info, and copy the port number from the second field:

$ curl http://hostname/ssh_info
hostname 29418

If you are developing an automated tool to perform uploads to Gerrit, let the user supply the hostname or the web address for Gerrit, and obtain the port number on the fly from the /ssh_info URL. The returned output from this URL is always 'hostname' SP 'port', or NOT_AVAILABLE if the SSHD server is not currently running.

git push

Create Changes

To create new changes for review, simply push to the project’s magical refs/for/'branch' ref using any Git client tool:

git push ssh://sshusername@hostname:29418/projectname HEAD:refs/for/branchname

E.g. john.doe can use git push to upload new changes for the experimental branch of project kernel/common, hosted at the Gerrit server:

git push ssh:// HEAD:refs/for/experimental

Each new commit uploaded by the git push client will be converted into a change record on the server. The remote ref refs/for/experimental is not actually created by Gerrit, even though the client’s status messages may say otherwise.

Other users (e.g. project owners) who have configured Gerrit to notify them of new changes will be automatically sent an email message when the push is completed.

To include a short tag associated with all of the changes in the same group, such as the local topic branch name, append it after the destination branch name. In this example the short topic tag driver/i42 will be saved on each change this push creates or updates:

git push ssh:// HEAD:refs/for/experimental/driver/i42

If you are frequently uploading changes to the same Gerrit server, consider adding an SSH host block in ~/.ssh/config to remember your username, hostname and port number. This permits the use of shorter URLs on the command line, such as:

$ cat ~/.ssh/config
Host tr
  Port 29418
  User john.doe
$ git push tr:kernel/common HEAD:refs/for/experimental

Specific reviewers can be requested and/or additional carbon copies of the notification message may be sent by including these as arguments to git receive-pack:

git push --receive-pack='git receive-pack' tr:kernel/common HEAD:refs/for/experimental

The --reviewer='email' and --cc='email' options may be specified as many times as necessary to cover all interested parties. Gerrit will automatically avoid sending duplicate email notifications, such as if one of the specified reviewers or CC addresses had also requested to receive all new change notifications.

If you are frequently sending changes to the same parties and/or branches, consider adding a custom remote block to your project’s .git/config file:

$ cat .git/config
[remote "for-a-exp"]
  url = tr:kernel/common
  receivepack = git receive-pack
  push = HEAD:refs/for/experimental
$ git push for-a-exp

Replace Changes

To add an additional patch set to a change, ensure Change-Id lines were created in the original commit messages, and just use git push URL HEAD:refs/for/... as described above. Gerrit Code Review will automatically match the commits back to their original changes by taking advantage of the Change-Id lines.

If Change-Id lines are not present in the commit messages, consider amending the message and copying the line from the change’s page on the web, and then using git push as described above.

If Change-Id lines are not available, then the user must use the manual mapping technique described below.

For more about Change-Ids, see Change-Id Lines.

Manual Replacement Mapping

Deprecation Warning

The remainder of this section describes a manual method of replacing changes by matching each commit name to an existing change number. End-users should instead prefer to use Change-Id lines in their commit messages, as the process is then fully automated by Gerrit during normal uploads.

See above for the preferred technique of replacing changes.

To add an additional patch set to a change, replacing it with an updated version of the same logical modification, send the new commit to the change’s ref. For example, to add the commit whose SHA-1 starts with c0ffee as a new patch set for change number 1979, use the push refspec c0ffee:refs/changes/1979 as below:

git push ssh://sshusername@hostname:29418/projectname c0ffee:refs/changes/1979

This form can be combined together with refs/for/'branchname' (above) to simultaneously create new changes and replace changes during one network transaction.

For example, consider the following sequence of events:

$ git commit -m A                    ; # create 3 commits
$ git commit -m B
$ git commit -m C
$ git push ... HEAD:refs/for/master  ; # upload for review
... A is 1500 ...
... B is 1501 ...
... C is 1502 ...
$ git rebase -i HEAD~3               ; # edit "A", insert D before B
                                     ; # now series is A'-D-B'-C'
$ git push ...
    HEAD~0:refs/changes/1502         ; # upload replacements

At the final step during the push Gerrit will attach A' as a new patch set on change 1500; B' as a new patch set on change 1501; C' as a new patch set on 1502; and D will be created as a new change.

Ensuring D is created as a new change requires passing the refspec HEAD:refs/for/branchname, otherwise Gerrit will ignore D and won’t do anything with it. For this reason it is a good idea to always include the create change refspec when uploading replacements.

Bypass Review

Changes (and annotated tags) can be pushed directly into a repository, bypassing the review process. This is primarily useful for a project owner to create new branches, create annotated tags for releases, or to force-update a branch whose history needed to be rewritten.

Gerrit restricts direct pushes that bypass review to:

  • refs/heads/*: any branch can be updated, created, deleted, or rewritten by the pusher.

  • refs/tags/*: annotated tag objects pointing to any other type of Git object can be created.

To push branches, the proper access rights must be configured first. Here follows a few examples of how to configure this in Gerrit:

  • Update: Any existing branch can be fast-forwarded to a new commit. This is the safest mode as commits cannot be discarded. Creation of new branches is rejected. Can be configured with Push access.

  • Create: Allows creation of a new branch if the name does not already designate an existing branch name. Needs Create Reference configured. Please note that once created, this permission doesn’t grant the right to update the branch with further commits (see above for update details).

  • Delete: Implies Update, but also allows an existing branch to be deleted. Since a force push is effectively a delete followed by a create, but performed atomically on the server and logged, this also permits forced push updates to branches. To grant this access, configure Push with the Force option ticked.

To push annotated tags, the Push Annotated Tag project right must be granted to one (or more) of the user’s groups. There is only one level of access in this category.

Project owners may wish to grant themselves Push Annotated Tag only at times when a new release is being prepared, and otherwise grant nothing at all. This ensures that accidental pushes don’t make undesired changes to the public repository.

repo upload

repo is a multiple repository management tool, most commonly used by the Android Open Source Project. For more details, see using repo.

Create Changes

To upload changes to a project using repo, ensure the manifest’s review field has been configured to point to the Gerrit server. Only the hostname or the web address needs to be given in the manifest file. During upload repo will automatically determine the correct port number by reading http://'reviewhostname'/ssh_info when its invoked.

Each new commit uploaded by repo upload will be converted into a change record on the server. Other users (e.g. project owners) who have configured Gerrit to notify them of new changes will be automatically sent an email message. Additional notifications can be sent through command line options.

For more details on using repo upload, see repo help upload.

Replace Changes

To replace changes, ensure Change-Id lines were created in the commit messages, and just use repo upload. Gerrit Code Review will automatically match the commits back to their original changes by taking advantage of their Change-Id lines.

If Change-Id lines are not present in the commit messages, consider amending the message and copying the line from the change’s page on the web.

If Change-Id lines are not available, then the user must use the much more manual mapping technique offered by using git push to a specific refs/changes/change# reference.

For more about Change-Ids, see Change-Id Lines.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。如发现有害或侵权内容,请点击这里 或 拨打24小时举报电话:4000070609 与我们联系。




    请遵守用户 评论公约

    喜欢该文的人也喜欢 更多