diff options
author | Shawn O. Pearce <sop@google.com> | 2009-01-29 08:42:41 -0800 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2009-01-29 08:53:10 -0800 |
commit | e61a3c6369c7df9075ce93caa217e1fcfe6c614e (patch) | |
tree | c8c148ca3d47b9b98572b4d7db7a8eadf77aa894 | |
parent | e43a8e6daadf46a2fc8034a510474fcb343703a0 (diff) |
Add user level documentation about how to upload changes over SSH
Signed-off-by: Shawn O. Pearce <sop@google.com>
-rw-r--r-- | Documentation/user-upload.txt | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/Documentation/user-upload.txt b/Documentation/user-upload.txt new file mode 100644 index 0000000000..fef0d0a7f5 --- /dev/null +++ b/Documentation/user-upload.txt @@ -0,0 +1,319 @@ +Gerrit2 - Uploading Changes +=========================== + +Gerrit supports three methods of uploading changes for review: + +* 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 use SSH public key authentication, which must +first be configured by the uploading user. + +SSH Authentication +------------------ + +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 `My` > `Settings` (or by visting +`http://'hostname'/settings`) then accessing the `SSH Keys` tab. + +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. + +[NOTE] +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 your 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 use Gerrit to upload changes will also want +to consider starting a `ssh-agent`, and adding their 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 Your SSH Connection +--------------------------- + +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` is always the local part of your +preferred email address (the text before the `@` sign). The exact +value chosen by Gerrit can be confirmed by visting `My` > `Settings`, +and copying the `SSH Username` field. For example, a user who +has selected a preferred email address of `john.doe@example.com` +would be assigned `john.doe` as their SSH username. For many +users, this may also be identical to their local username. + +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 +==== + +[TIP] +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 isn't running. + + +repo upload: 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`. + + +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. + +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 `gerrit receive-pack`: + +==== + git push --receive-pack='gerrit 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 = gerrit receive-pack --reviewer=a@a.com --cc=b@o.com + push = HEAD:refs/for/experimental + + $ git push for-a-exp +==== + + +git push: Replace 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: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. + + +git push: 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. Tags cannot be updated or deleted. + +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. + + +Gritty Details +-------------- + +Gerrit requires that the tuple `('username', 'public_key')` +be unique. When it gets a login request it scans all accounts +whose SSH Username matches the name requested by the client, to +see if any of them have the public key presented by the client. + +What this means is, say there's "john.doe@example.com" (me) and +"john.doe@evil.com" (someone else - not me). Gerrit will consider +both accounts' public keys when I login, but only binds the session +to the account whose key was presented. If multiple accounts match +the same key and same username, it denies the login. + +Given that most local names will be unique across a single Gerrit +server, that means in practice most people will only be considering +their own keys. Since SSH keys (in theory) are globally unique, +even if two people have the same local name, they still can't access +each other's accounts. But, if two people both used Debian's broken +ssh-keygen and they have the same local name, they effectively lock +each other out of Gerrit until one (or both) changes their key(s) +to a more secure one. + +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. |