Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 1 | Gerrit2 - Uploading Changes |
| 2 | =========================== |
| 3 | |
| 4 | Gerrit supports three methods of uploading changes for review: |
| 5 | |
| 6 | * Use `repo upload`, to create changes for review |
| 7 | * Use `git push`, to create changes for review |
| 8 | * Use `git push`, and bypass code review |
| 9 | |
| 10 | All three methods use SSH public key authentication, which must |
| 11 | first be configured by the uploading user. |
| 12 | |
| 13 | SSH Authentication |
| 14 | ------------------ |
| 15 | |
Shawn O. Pearce | e85964c | 2009-05-28 11:16:24 -0700 | [diff] [blame] | 16 | Each user uploading changes to Gerrit must configure one |
| 17 | or more SSH public keys. The per-user SSH key list can be |
| 18 | accessed over the web within Gerrit by `Settings` (or by visting |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 19 | `http://'hostname'/settings`) then accessing the `SSH Keys` tab. |
| 20 | |
| 21 | To register a new SSH key for use with Gerrit, paste the contents |
| 22 | of your `id_rsa.pub` or `id_dsa.pub` file into the text box and |
| 23 | click the add button. |
| 24 | |
| 25 | [NOTE] |
| 26 | Gerrit only understands SSH version 2 public keys. Keys may be |
| 27 | supplied in either the OpenSSH format (key starts with `ssh-rsa` |
| 28 | or `ssh-dss`) or the RFC 4716 format (file starts with `---- BEGIN |
| 29 | SSH2 PUBLIC KEY ----`). |
| 30 | |
| 31 | Typically your SSH keys are stored in your home directory, under |
| 32 | `~/.ssh`. If you don't have any keys yet, you can create a new |
| 33 | one and protect it with a passphrase: |
| 34 | |
| 35 | ==== |
| 36 | ssh-keygen -t rsa |
| 37 | ==== |
| 38 | |
| 39 | Then copy the content of the public key file onto your clipboard, |
| 40 | and paste it into Gerrit's web interface: |
| 41 | |
| 42 | ==== |
| 43 | cat ~/.ssh/id_rsa.pub |
| 44 | ==== |
| 45 | |
| 46 | [TIP] |
| 47 | Users who frequently use Gerrit to upload changes will also want |
| 48 | to consider starting a `ssh-agent`, and adding their key to the |
| 49 | list managed by the agent, to reduce the frequency of entering the |
| 50 | key's passphrase. Consult `man ssh-agent`, or your SSH client's |
| 51 | documentation, for more details on configuration of the agent |
| 52 | process and how to add the private key. |
| 53 | |
Shawn O. Pearce | 4016a93 | 2009-05-28 15:12:40 -0700 | [diff] [blame] | 54 | Testing Your SSH Connection[[test_ssh]] |
| 55 | --------------------------------------- |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 56 | |
| 57 | To verify your SSH key is working correctly, try using an SSH client |
| 58 | to connect to Gerrit's SSHD port. By default Gerrit is running on |
| 59 | port 29418, using the same hostname as the web server: |
| 60 | |
| 61 | ==== |
| 62 | $ ssh -p 29418 sshusername@hostname |
| 63 | gerrit: no shell available |
| 64 | Connection to hostname closed. |
| 65 | ==== |
| 66 | |
| 67 | In the command above, `sshusername` is always the local part of your |
| 68 | preferred email address (the text before the `@` sign). The exact |
Shawn O. Pearce | e85964c | 2009-05-28 11:16:24 -0700 | [diff] [blame] | 69 | value chosen by Gerrit can be confirmed by visting `Settings`, |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 70 | and copying the `SSH Username` field. For example, a user who |
| 71 | has selected a preferred email address of `john.doe@example.com` |
Shawn O. Pearce | e85964c | 2009-05-28 11:16:24 -0700 | [diff] [blame] | 72 | would be assigned `john.doe` as their SSH username. For many users, |
| 73 | this may also be identical to their local username. |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 74 | |
| 75 | To determine the port number Gerrit is running on, visit the special |
| 76 | information URL `http://'hostname'/ssh_info`, and copy the port |
| 77 | number from the second field: |
| 78 | |
| 79 | ==== |
| 80 | $ curl http://hostname/ssh_info |
| 81 | hostname 29418 |
| 82 | ==== |
| 83 | |
| 84 | [TIP] |
| 85 | If you are developing an automated tool to perform uploads to Gerrit, |
| 86 | let the user supply the hostname or the web address for Gerrit, |
| 87 | and obtain the port number on the fly from the `/ssh_info` URL. |
| 88 | The returned output from this URL is always `'hostname' SP 'port'`, |
| 89 | or `NOT_AVAILABLE` if the SSHD server isn't running. |
| 90 | |
| 91 | |
| 92 | repo upload: Create Changes |
| 93 | --------------------------- |
| 94 | |
| 95 | To upload changes to a project using `repo`, ensure the manifest's |
| 96 | review field has been configured to point to the Gerrit server. |
| 97 | Only the hostname or the web address needs to be given in the |
| 98 | manifest file. During upload `repo` will automatically determine the |
| 99 | correct port number by reading `http://'reviewhostname'/ssh_info` |
| 100 | when its invoked. |
| 101 | |
| 102 | Each new commit uploaded by `repo upload` will be converted into |
| 103 | a change record on the server. Other users (e.g. project owners) |
| 104 | who have configured Gerrit to notify them of new changes will be |
| 105 | automatically sent an email message. Additional notifications can |
| 106 | be sent through command line options. |
| 107 | |
| 108 | For more details on using `repo upload`, see `repo help upload`. |
| 109 | |
| 110 | |
Shawn O. Pearce | 4016a93 | 2009-05-28 15:12:40 -0700 | [diff] [blame] | 111 | git push: Create Changes[[push_create]] |
| 112 | --------------------------------------- |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 113 | |
| 114 | To create new changes for review, simply push into the project's |
| 115 | magical `refs/for/'branch'` ref using any Git client tool: |
| 116 | |
| 117 | ==== |
| 118 | git push ssh://sshusername@hostname:29418/projectname HEAD:refs/for/branchname |
| 119 | ==== |
| 120 | |
| 121 | E.g. `john.doe` can use git push to upload new changes for the |
| 122 | `experimental` branch of project `kernel/common`, hosted at the |
| 123 | `git.example.com` Gerrit server: |
| 124 | |
| 125 | ==== |
| 126 | git push ssh://john.doe@git.example.com:29418/kernel/common HEAD:refs/for/experimental |
| 127 | ==== |
| 128 | |
| 129 | Each new commit uploaded by the `git push` client will be |
| 130 | converted into a change record on the server. The remote ref |
| 131 | `refs/for/experimental` is not actually created by Gerrit, even |
| 132 | though the client's status messages may say otherwise. |
| 133 | |
| 134 | Other users (e.g. project owners) who have configured Gerrit to |
| 135 | notify them of new changes will be automatically sent an email |
| 136 | message when the push is completed. |
| 137 | |
| 138 | If you are frequently uploading changes to the same Gerrit server, |
| 139 | consider adding an SSH host block in `~/.ssh/config` to remember |
| 140 | your username, hostname and port number. This permits the use of |
| 141 | shorter URLs on the command line, such as: |
| 142 | |
| 143 | ==== |
| 144 | $ cat ~/.ssh/config |
| 145 | ... |
| 146 | Host tr |
| 147 | Hostname git.example.com |
| 148 | Port 29418 |
| 149 | User john.doe |
| 150 | |
| 151 | $ git push tr:kernel/common HEAD:refs/for/experimental |
| 152 | ==== |
| 153 | |
| 154 | Specific reviewers can be requested and/or additional ``carbon |
| 155 | copies'' of the notification message may be sent by including these |
Shawn O. Pearce | fc0ec2f | 2009-05-28 11:20:06 -0700 | [diff] [blame] | 156 | as arguments to `git receive-pack`: |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 157 | |
| 158 | ==== |
Shawn O. Pearce | fc0ec2f | 2009-05-28 11:20:06 -0700 | [diff] [blame] | 159 | git push --receive-pack='git receive-pack --reviewer=a@a.com --cc=b@o.com' tr:kernel/common HEAD:refs/for/experimental |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 160 | ==== |
| 161 | |
| 162 | The `\--reviewer='email'` and `\--cc='email'` options may be |
| 163 | specified as many times as necessary to cover all interested |
| 164 | parties. Gerrit will automatically avoid sending duplicate email |
| 165 | notifications, such as if one of the specified reviewers or CC |
| 166 | addresses had also requested to receive all new change notifications. |
| 167 | |
| 168 | If you are frequently sending changes to the same parties and/or |
| 169 | branches, consider adding a custom remote block to your project's |
| 170 | `.git/config` file: |
| 171 | |
| 172 | ==== |
| 173 | $ cat .git/config |
| 174 | ... |
| 175 | [remote "for-a-exp"] |
| 176 | url = tr:kernel/common |
Shawn O. Pearce | fc0ec2f | 2009-05-28 11:20:06 -0700 | [diff] [blame] | 177 | receivepack = git receive-pack --reviewer=a@a.com --cc=b@o.com |
Shawn O. Pearce | e61a3c6 | 2009-01-29 08:42:41 -0800 | [diff] [blame] | 178 | push = HEAD:refs/for/experimental |
| 179 | |
| 180 | $ git push for-a-exp |
| 181 | ==== |
| 182 | |
| 183 | |
| 184 | git push: Replace Changes |
| 185 | ------------------------- |
| 186 | |
| 187 | To add an additional patch set to a change, replacing it with an |
| 188 | updated version of the same logical modification, send the new |
| 189 | commit to the change's ref. For example, to add the commit whose |
| 190 | SHA-1 starts with `c0ffee` as a new patch set for change number |
| 191 | `1979`, use the push refspec `c0ffee:refs/changes/1979` as below: |
| 192 | |
| 193 | ==== |
| 194 | git push ssh://sshusername@hostname:29418/projectname c0ffee:refs/changes/1979 |
| 195 | ==== |
| 196 | |
| 197 | This form can be combined together with `refs/for/'branchname'` |
| 198 | (above) to simultaneously create new changes and replace changes |
| 199 | during one network transaction. |
| 200 | |
| 201 | For example, consider the following sequence of events: |
| 202 | |
| 203 | ==== |
| 204 | $ git commit -m A ; # create 3 commits |
| 205 | $ git commit -m B |
| 206 | $ git commit -m C |
| 207 | |
| 208 | $ git push ... HEAD:refs/for/master ; # upload for review |
| 209 | ... A is 1500 ... |
| 210 | ... B is 1501 ... |
| 211 | ... C is 1502 ... |
| 212 | |
| 213 | $ git rebase -i HEAD~3 ; # edit "A", insert D before B |
| 214 | ; # now series is A'-D-B'-C' |
| 215 | $ git push ... |
| 216 | HEAD:refs/for/master |
| 217 | HEAD~3:refs/changes/1500 |
| 218 | HEAD~1:refs/changes/1501 |
| 219 | HEAD~0:refs/changes/1502 ; # upload replacements |
| 220 | ==== |
| 221 | |
| 222 | At the final step during the push Gerrit will attach A' as a new |
| 223 | patch set on change 1500; B' as a new patch set on change 1501; C' |
| 224 | as a new patch set on 1502; and D will be created as a new change. |
| 225 | |
| 226 | Ensuring D is created as a new change requires passing the refspec |
| 227 | `HEAD:refs/for/branchname`, otherwise Gerrit will ignore D and |
| 228 | won't do anything with it. For this reason it is a good idea to |
| 229 | always include the create change refspec when uploading replacements. |
| 230 | |
| 231 | |
| 232 | git push: Bypass Review |
| 233 | ----------------------- |
| 234 | |
| 235 | Changes (and annotated tags) can be pushed directly into a |
| 236 | repository, bypassing the review process. This is primarily useful |
| 237 | for a project owner to create new branches, create annotated tags |
| 238 | for releases, or to force-update a branch whose history needed to |
| 239 | be rewritten. |
| 240 | |
| 241 | Gerrit restricts direct pushes that bypass review to: |
| 242 | |
| 243 | * `refs/heads/*`: any branch can be updated, created, deleted, |
| 244 | or rewritten by the pusher. |
| 245 | * `refs/tags/*`: annotated tag objects pointing to any other type |
| 246 | of Git object can be created. Tags cannot be updated or deleted. |
| 247 | |
| 248 | To push branches, the `Push Branch` project right must be granted |
| 249 | to one (or more) of the user's groups. The allowed levels within |
| 250 | this category are: |
| 251 | |
| 252 | * Update: Any existing branch can be fast-forwarded to a new commit. |
| 253 | This is the safest mode as commits cannot be discarded. Creation |
| 254 | of new branches is rejected. |
| 255 | * Create: Implies Update, but also allows creation of a new branch |
| 256 | if the name does not not already designate an existing branch name. |
| 257 | * Delete: Implies Create and Update, but also allows an existing |
| 258 | branch to be deleted. Since a force push is effectively a delete |
| 259 | followed by a create, but performed atomically on the server and |
| 260 | logged, this also permits forced push updates to branches. |
| 261 | |
| 262 | To push annotated tags, the `Push Annotated Tag` project right must |
| 263 | be granted to one (or more) of the user's groups. There is only |
| 264 | one level of access in this category. |
| 265 | |
| 266 | Project owners may wish to grant themselves `Push Annotated Tag` |
| 267 | only at times when a new release is being prepared, and otherwise |
| 268 | grant nothing at all. This ensures that accidental pushes don't |
| 269 | make undesired changes to the public repository. |
| 270 | |
| 271 | |
| 272 | Gritty Details |
| 273 | -------------- |
| 274 | |
| 275 | Gerrit requires that the tuple `('username', 'public_key')` |
| 276 | be unique. When it gets a login request it scans all accounts |
| 277 | whose SSH Username matches the name requested by the client, to |
| 278 | see if any of them have the public key presented by the client. |
| 279 | |
| 280 | What this means is, say there's "john.doe@example.com" (me) and |
| 281 | "john.doe@evil.com" (someone else - not me). Gerrit will consider |
| 282 | both accounts' public keys when I login, but only binds the session |
| 283 | to the account whose key was presented. If multiple accounts match |
| 284 | the same key and same username, it denies the login. |
| 285 | |
| 286 | Given that most local names will be unique across a single Gerrit |
| 287 | server, that means in practice most people will only be considering |
| 288 | their own keys. Since SSH keys (in theory) are globally unique, |
| 289 | even if two people have the same local name, they still can't access |
| 290 | each other's accounts. But, if two people both used Debian's broken |
| 291 | ssh-keygen and they have the same local name, they effectively lock |
| 292 | each other out of Gerrit until one (or both) changes their key(s) |
| 293 | to a more secure one. |
| 294 | |
| 295 | As Gerrit implements the entire SSH and Git server stack within its |
| 296 | own process space, Gerrit maintains complete control over how the |
| 297 | repository is updated, and what responses are sent to the `git push` |
| 298 | client invoked by the end-user, or by `repo upload`. This allows |
| 299 | Gerrit to provide magical refs, such as `refs/for/\*` for new |
| 300 | change submission and `refs/changes/\*` for change replacement. |
| 301 | When a push request is received to create a ref in one of these |
| 302 | namespaces Gerrit performs its own logic to update the database, |
| 303 | and then lies to the client about the result of the operation. |
| 304 | A successful result causes the client to believe that Gerrit has |
| 305 | created the ref, but in reality Gerrit hasn't created the ref at all. |
| 306 | |
| 307 | By implementing the entire server stack, Gerrit is also able to |
| 308 | perform project level access control checks (to verify the end-user |
| 309 | is permitted to access a project) prior to advertising the available |
| 310 | refs, and potentially leaking information to a snooping client. |
| 311 | Clients cannot tell the difference between 'project not found' and |
| 312 | 'project exists, but access is denied'. |
| 313 | |
| 314 | Gerrit can also ensure users have completed a valid Contributor |
| 315 | Agreement prior to accepting any transferred objects, and if an |
| 316 | agreement is required, but not completed, it aborts the network |
| 317 | connection before data is sent. This ensures that project owners |
| 318 | can be certain any object available in their repository has been |
| 319 | supplied under at least one valid agreement. |
Shawn O. Pearce | 5500e69 | 2009-05-28 15:55:01 -0700 | [diff] [blame] | 320 | |
| 321 | GERRIT |
| 322 | ------ |
| 323 | Part of link:index.html[Gerrit Code Review] |