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.
SSH
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 Keys tab.
Configuration
To register a new SSH key for use with Gerrit, paste the contents of your id_rsa.pub or id_dsa.pub 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/id_rsa.pub
Tip
|
Users who frequently upload changes will also want to consider starting a 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 is running on port 29418, using the same hostname as the web server:
$ ssh -p 29418 sshusername@hostname gerrit: no shell available Connection to hostname closed.
In the command above, sshusername was configured on the SSH Keys tab of the Settings screen. If it is not set, propose a name and use Change 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 into 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 git.example.com Gerrit server:
git push ssh://john.doe@git.example.com:29418/kernel/common 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://john.doe@git.example.com:29418/kernel/common 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 Hostname git.example.com 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 --reviewer=a@a.com --cc=b@o.com' 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 --reviewer=a@a.com --cc=b@o.com 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
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:refs/for/master HEAD~3:refs/changes/1500 HEAD~1:refs/changes/1501 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 Push Branch project right must be granted to one (or more) of the user’s groups. The allowed levels within this category are:
-
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.
-
Create: Implies Update, but also allows creation of a new branch if the name does not not already designate an existing branch name.
-
Delete: Implies Create and 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 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 without the \--replace command line flag. 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 repo upload \--replace.
For more about Change-Ids, see Change-Id Lines.
Gritty Details
As Gerrit implements the entire SSH and Git server stack within its own process space, Gerrit maintains complete control over how the repository is updated, and what responses are sent to the git push client invoked by the end-user, or by repo upload. This allows Gerrit to provide magical refs, such as refs/for/\* for new change submission and refs/changes/\* for change replacement. When a push request is received to create a ref in one of these namespaces Gerrit performs its own logic to update the database, and then lies to the client about the result of the operation. A successful result causes the client to believe that Gerrit has created the ref, but in reality Gerrit hasn’t created the ref at all.
By implementing the entire server stack, Gerrit is also able to perform project level access control checks (to verify the end-user is permitted to access a project) prior to advertising the available refs, and potentially leaking information to a snooping client. Clients cannot tell the difference between project not found and project exists, but access is denied.
Gerrit can also ensure users have completed a valid Contributor Agreement prior to accepting any transferred objects, and if an agreement is required, but not completed, it aborts the network connection before data is sent. This ensures that project owners can be certain any object available in their repository has been supplied under at least one valid agreement.
Part of Gerrit Code Review