Integrating Chromium Commits with Gerrit via git cl upload

This article explains how the git cl upload command from Chromium’s depot_tools bridges the gap between a developer's local Git environment and the Gerrit code review server. It covers the automated workflow of the command, including upstream branch comparison, local presubmit validation, Change-Id management, local configuration tracking, and the underlying network operations that create or update ChangeLists for the Chromium web browser project.

Branch Comparison and Commit Squashing

In Chromium development, a single local Git branch corresponds to a single ChangeList (CL) in Gerrit. When you run git cl upload, the tool first determines the diff by comparing your current local branch against its tracked upstream branch, which is typically origin/main.

Even if you have made multiple local commits on your working branch, git cl upload treats the entire branch as one logical change. By default, it squashes all local commits on that branch into a single commit payload before sending it to Gerrit, ensuring that reviewers see one unified patchset.

Local Presubmit Checks

Before transmitting any data to the Gerrit server, git cl upload runs a suite of local validation scripts known as presubmit checks. The tool traverses the repository's directory tree to locate PRESUBMIT.py files relevant to the modified files in your commit.

These scripts automatically verify that your code adheres to Chromium's strict guidelines. They check for proper code formatting (such as git cl format), valid license headers, correct OWNERS file syntax, and common programming errors. If a critical presubmit error is detected, the upload process aborts immediately, forcing you to fix the issue locally before consuming server resources or reviewer time.

Change-Id Generation and Commit Description

Gerrit relies on a unique identifier called a Change-Id located in the footer of the commit message to associate multiple patchsets with the same code review issue.

During the upload process, git cl upload opens your text editor to allow you to write or edit the CL description, which is pre-populated using your local commit messages. Once you save and close the editor, the tool checks for the presence of a Change-Id line. If one does not exist, git cl generates a unique SHA-1 hash prefixed with the letter "I" and injects it into the footer of your commit message, amending your local Git commit automatically.

Tracking State in the Local Git Configuration

To ensure that future uploads from the same branch update the existing Gerrit review instead of creating a new one, git cl stores metadata in your local .git/config file.

When an upload succeeds, the tool writes the Gerrit issue number, the server URL, and the base commit hash directly under the configuration section for your current branch (for example, branch.<branch-name>.gerritissue). On subsequent runs of git cl upload, the script reads these values from .git/config to know exactly which Gerrit issue to target with the new patchset.

Pushing to Gerrit Refs and API Integration

The final stage of git cl upload is the network transfer, which combines standard Git protocols with Gerrit's REST API.

Instead of pushing directly to the main branch, git cl executes an underlying git push command directed at Gerrit’s special magic reference namespace: refs/for/main. Pushing to this target instructs the Gerrit server to intercept the commit and stage it for code review rather than merging it into the codebase.

Simultaneously, git cl communicates with the Gerrit REST API over HTTPS. It authenticates using credentials stored in your local .gitcookies file and applies metadata to the CL. This API call sets the patchset title, assigns reviewers (via the -r flag), adds CC recipients, and can even trigger the Chromium Commit Queue (via the --use-commit-queue or -d flags) to begin automated trybot testing immediately upon upload.