Git/Gerrit Code Review

Gerrit is a web-based code review tool for projects using the Git VCS. It allows both a streamlined code review process, and a highly-configurable hierarchy for project members. Typically, any user may submit patches ("changesets") to the server for review. Once someone has reviewed the changes to a sufficient degree, they are merged into the main line of development, which can then be pulled.

Server
Gerrit uses a dedicated Jetty server, which is typically accessed via reverse proxy. Here's an example configuration for Apache:  ProxyRequests Off ProxyVia Off ProxyPreserveHost On     Order deny,allow Allow from all  # Reverse-proxy these requests to the Gerrit Jetty server RedirectMatch ^/gerrit$                /gerrit/ ProxyPass      /gerrit/                http://127.0.0.1:8081/gerrit/ 

JGit
Gerrit uses JGit, a Java implementation of git. This has several limitations: a sacrifice in speed, and some unimplemented features. For example, content-level merges are not supported in JGit - users must pull and merge changes, then re-upload them to the Gerrit server in cases where content-level merges are required.

Permissions model
Gerrit's permissions model allows a highly configurable hierarchy regarding who can submit patches, and who can review patches. This can be flattened out as desired, or ramped up, depending on the development model used for each project.

Hooks
The server allows scripts to run in response to certain events. Hook scripts live in $GIT_INSTALL_BASE/hooks, and must be set executable on Unix systems. A hook could - for instance - allow a project to install an automated gatekeeper to vote +2 'submit approved' when sufficient +1 votes 'looks good to me' have been received:

Importing project into Gerrit
Whether or not you're permitted to do this depends on which access group(s) you're in, and where you're trying to do this. It is most useful for pushing pre-existing repos to the server, but it can in theory be used whenever you want to push changes which are not to be reviewed.

Use: $ git push gerrit:project HEAD:refs/heads/master since you want to directly push into the branch, rather than create code reviews. Pushing to  creates code reviews which must be approved and then submitted. Pushing to  bypasses review entirely, and just enters the commits directly into the branch. The latter does not check committer identity, making it appropriate for importing past project history.

The correct permission setup can be found here: http://stackoverflow.com/questions/8353988/how-to-upload-a-git-repo-to-gerrit. In addition, "Push Merge Commit" for "refs/*" may be needed for some repositories (for details see http://code.google.com/p/gerrit/issues/detail?id=1072).

Submitting changes for review
Simply push into the project's magical  (typically master) ref using any Git client tool: $ git push ssh://user@host:29418/project HEAD:refs/for/master

Each new commit uploaded by the git push client will be converted into a change record on the server. The remote ref  is not actually created by Gerrit, even though the client's status messages may say otherwise. Pushing to this magical branch submits changes for review. Once you have pushed changes, they must be reviewed and submitted for merging to whatever branch they apply to. You can clone/pull from gerrit as you would any other git repo (no refs/for/branch, just use the branch name): $ git clone ssh://user@host:29418/project $ git pull ssh://user@host:29418/project master:testbranch

Gerrit currently has no, so pulling is via ssh, and therefore comparatively slow (but secure). You can run  for the repositories to make them available via , or configure Gerrit to replicate changes to another git repository, where you can pull from.

Since you will be frequently working with the same Gerrit server, add 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 as shown, such as: $ tail -n 4 ~/.ssh/config Host gerrit Hostname host.com Port 29418 User john.doe $ git push gerrit:project HEAD:refs/for/master

Alternatively, you can also configure your remotes in git's configuration file by issuing: $ git config remote.remote_name.fetch +refs/heads/*:refs/remotes/origin/* $ git config remote.remote_name.url ssh://user@host:29418/project_name.git

This should be done automatically for you if you've started your local repository off of Gerrit's project repository using $ git clone ssh://user@host:29418/project_name.git

Note that the Gerrit server has its own sshd with different host keys. Some ssh clients will complain about this bitterly.

Re-submitting a changeset
This is useful when there are issues with a commit you pushed. Maybe you caught them, maybe the reviewer did – either way, you want to submit changes for review, replacing the bad changes you submitted previously. This keeps code review in one place, streamlining the process. First, squash your changes into one commit using git rebase -i – you will probably want to change the commit message.

This doesn't actually replace the previous push, it just adds your updated changeset as a newer version.

You can provide a Change-Id line in your commit message: it must be in the bottom portion (last paragraph) of a commit message, and may be mixed together with the Signed-off-by, Acked-by, or other such footers. The Change-Id is available in the metadata table for your initial pushed commit. In this case, Gerrit will automatically match this changeset to the previous one.

Alternatively, you can push to a special location: the  branch. To replace changeset 12345, you push to. This number can be found in the URL when looking at the changeset you wish to replace:. You can also find it in the "download" section for the changeset:  (choose the middle number: ignore   and omit the trailing  ). In this case, your push becomes: $ git rebase -i HEAD~2 # squash the relevant commits, probably altering the commit message $ git push gerrit:project a95cc0dcd7a8fd3e70b1243aa466a96de08ae731:refs/changes/12345