Read Anthropic’s case study about Graphite Reviewer

Gerrit's Approach to Code Review

Greg Foster
Greg Foster
Graphite software engineer
Try Graphite

Gerrit is an open-source code review system built on top of Git. It allows developers to push commits into a special review process instead of directly pushing them to a repository. Gerrit offers a web-based UI for discussing and reviewing changes, setting review labels (for example, +2 or -2), and eventually merging or rejecting those changes. Gerrit was originally developed at Google and then open-sourced for broader adoption.

The key advantages of using Gerrit for code review include:

  • Patch-based review: Each commit is treated as a proposed patch set, which can be updated iteratively.
  • Inline and side-by-side diffs: Reviewers can add line-level comments and suggestions.
  • Gatekeeping: Gerrit blocks changes from being merged unless they have the required review approvals.
  • Integration: Gerrit easily integrates with CI/CD systems (for example, Jenkins) to automate verification.

A change in Gerrit corresponds to one proposed modification to the codebase. A change typically starts as a single commit pushed to Gerrit. If a developer needs to modify their commit in response to code review feedback, they amend the commit locally and push it again—this creates a patch set. Multiple patch sets can exist for a single Gerrit change as it evolves.

In Gerrit, changes are stored under special references in Git (for example, refs/for/master). Instead of pushing to a Git branch (like master), a user pushes to these special refs to indicate that the commit is intended for review. Gerrit then tracks the change internally and displays it in the Gerrit UI.

A project in Gerrit maps to a Git repository. Within each project, you can have multiple branches (for example, master, release-1.0, etc.). Gerrit enforces permissions and approval workflows on a per-branch basis.

One of Gerrit’s strengths is its granular permission model. Permissions can be set at the project level or the branch level. For instance, you can require that only specific groups of developers can give the final approval for merges, or that certain changes require special verification.

  1. Checkout the repository from Gerrit or a Git mirror of the same repository.
  2. Create or update a commit locally (like any normal Git workflow).
  3. Push to Gerrit using a special refs/for/<branch> reference.
  4. Gerrit creates a change with a patch set in the web UI.
  5. Reviewers are automatically notified or assigned.
  6. Review occurs, with feedback provided as comments and scores.
  7. The developer addresses feedback by amending the commit locally and pushing a new patch set to the same refs (Gerrit automatically updates the existing change).
  8. Once reviews and all required checks pass, a reviewer with sufficient permissions submits the change.
  9. The change is merged into the target branch (for example, master).
  1. Checkout and make changes

    Terminal
    git clone ssh://[username]@gerrit.company.com:29418/my-project.git
    cd my-project
    # make local changes
    git add .
    git commit -m "Implement new feature"
  2. Push to Gerrit

    Terminal
    # Instead of pushing to 'master', push to 'refs/for/master'
    git push ssh://[username]@gerrit.company.com:29418/my-project.git HEAD:refs/for/master
  3. View and review

    • In the Gerrit UI, each commit is now listed as a change.
    • You can see the file diffs, add inline comments, and set review scores.
  4. Address feedback

    • Locally, amend or fix code in response to review.
      Terminal
      # amend the commit
      git commit --amend -m "Implement new feature (with feedback included)"
    • Push again, using the same syntax for Gerrit:
      Terminal
      git push ssh://[username]@gerrit.company.com:29418/my-project.git HEAD:refs/for/master
    • This updated commit is automatically recognized as a new patch set of the same change.
  5. Approve and merge

    • Once reviewers add the necessary approvals (for example, Code-Review: +2, Verified: +1), an authorized user can click Submit in the Gerrit UI.
    • Gerrit performs a merge (or rebase, depending on the settings) of the commit into the target branch.

By default, Gerrit has a Code-Review label that can take values like +2, +1, 0, -1, or -2:

  • +2: “Looks good to me; approved.” Typically means this reviewer is satisfied with the change and can give the final go-ahead.
  • +1: “Looks mostly good, but I’m not the final gate.” This often indicates a supportive comment, but not an approval to submit.
  • -1: “I have concerns. Please address them.” This is a blocking vote from a reviewer but not necessarily a veto.
  • -2: “This cannot be merged as-is.” Usually a stronger veto that might require bigger changes or a different approach.

A common practice is to have an automated CI server add a Verified label (for example, +1 if the build/tests pass, -1 if they fail). Gerrit will often block merges if the Verified score is missing or negative.

Depending on how Gerrit is configured, changes might need to be rebased onto the latest tip of the target branch before submission. Gerrit can do this automatically, or you can manually rebase locally:

Terminal
git fetch origin master
git rebase origin/master
git push ssh://[username]@gerrit.company.com:29418/my-project.git HEAD:refs/for/master

Gerrit has different submit strategies, such as:

  • Fast-forward only
  • Merge if necessary
  • Cherry-pick
  • Rebase always

Teams typically choose a strategy that fits their branching model and preference for merge commits or a linear history.

You can integrate Gerrit with Jenkins (or other CI systems) by setting up a Gerrit trigger plugin. When a developer pushes a new patch set, Jenkins can automatically:

  1. Fetch the patch set from Gerrit.
  2. Build and run tests.
  3. Report back with a Verified vote (+1 or -1).

Automated verification ensures that no human reviewer merges a patch that fails basic tests or style checks. This is particularly powerful when combined with code review feedback, as it automates part of the approval process.

  1. Small, focused changes

    • Keep your commits small and focused on a single purpose to make reviews more efficient.
  2. Commit messages

    • Provide descriptive commit messages; include a summary line and a more detailed description explaining why a change was made.
  3. Use topic branches

    • Gerrit supports “topics,” which help group related changes. Pushing with refs/for/master%topic=some_topic tags your changes for easier tracking.
  4. Respond quickly to feedback

    • Encourage a quick turnaround on feedback. If you see a -1, fix it or respond within a reasonable timeframe.
  5. Squash before submit

    • In some workflows, it’s common to squash patch sets if you want a single commit to represent the final merge. Gerrit tracks patch sets internally, but you may want a tidy Git history.
  6. Automate as much as possible

    • Hook in your CI to do builds, tests, code coverage, and style checks. This reduces the manual workload for reviewers.
  7. Check Gerrit hooks and plugins

    • Gerrit has a wide ecosystem of plugins that can add functionality (for example, replication to external Git servers, hooks for custom automation, etc.).

Gerrit provides a streamlined, patch-based approach to code review that integrates tightly with Git. By pushing changes to refs/for/<branch>, developers create changes and patch sets that can be iterated upon through review and feedback. Gerrit’s label-based approval system (Code-Review, Verified, etc.) ensures that only rigorously vetted code is merged. With additional integrations into CI/CD pipelines, Gerrit can form the backbone of a robust DevOps workflow, making code review both mandatory and efficient.

Built for the world's fastest engineering teams, now available for everyone