Gerrit » History » Version 40
neels, 07/12/2016 01:09 PM
1 | 1 | zecke | h1. Contributing using Gerrit |
---|---|---|---|
2 | |||
3 | 11 | laforge | {{>toc}} |
4 | |||
5 | 10 | laforge | At [[OpenBSC:OsmoDevCon2016]] we discussed problems with our past contribution / patch submission process using mails on the mailing list as well as patchwork. The result is that we want to give Gerrit a try for some time and see if it helps us to have a better process |
6 | 1 | zecke | |
7 | 10 | laforge | Gerrit is a review tool that integrates nicely with git and ssh. You can find general information about Gerrit at https://www.gerritcodereview.com/ |
8 | 1 | zecke | |
9 | 10 | laforge | The advantages of Gerrit are: |
10 | * patch submission status is automatically tracked, also with several revisions for a patch set. |
||
11 | * patches are build-tested (and possibly even further tested) by jenkins before they are applied |
||
12 | * developers + maintainers can formally vote on a patch (developer: -1/0/+1, maintainer: -2/0/+2) |
||
13 | * once a patch has +2 score, it can be (automatically) merged into master |
||
14 | * patch sumissions not via git send-email but direcly from git |
||
15 | |||
16 | h2. Osmocom Subprojects using Gerrit |
||
17 | |||
18 | 1 | zecke | The following projects use Gerrit to contribute changes: |
19 | |||
20 | * libosmocore.git |
||
21 | * libosmo-abis.git |
||
22 | * libosmo-netif.git |
||
23 | * libosmo-sccp.git |
||
24 | * libsmpp34.git |
||
25 | * openbsc.git |
||
26 | * osmo-bts.git |
||
27 | * osmo-iuh.git |
||
28 | * osmo-pcu.git |
||
29 | 5 | zecke | * cellmgr-ng.git |
30 | 1 | zecke | * osmo-sip-connector.git |
31 | 30 | neels | |
32 | 1 | zecke | h2. Configuring Gerrit/Account |
33 | |||
34 | 10 | laforge | You will need to sign-up at https://gerrit.osmocom.org/login/. If you have an Osmocom Redmine account you can use https://osmocom.org/openid as OpenID provider. If you have no Osmocom redmine account, you can simply create one online at the "Register" link in the upper right corner. |
35 | |||
36 | Even without an existing or new redmine account, you should also be able to use any other OpenID provider to authenticate against gerrit (untested). |
||
37 | |||
38 | After the initial sign-up you will need to: |
||
39 | 1 | zecke | |
40 | * Pick a username (can not be changed) |
||
41 | * Add your public ssh key(s) |
||
42 | * Add email addresses you intend to use as author/comitter |
||
43 | 30 | neels | |
44 | If you would like to push private branches to the Gerrit repository, you also need to be added to the "known users" group. |
||
45 | Please send a short requesting email to openbsc@lists.osmocom.org. |
||
46 | 1 | zecke | |
47 | h2. Setting up Gerrit for commits and pushing |
||
48 | |||
49 | 33 | neels | *Note:* it is easiest to work with gerrit when gerrit is the only remote in your git clone. |
50 | When you clone from git.osmocom.org and add the gerrit remote, git will have two remotes, |
||
51 | 36 | neels | so when you first checkout a branch you have to supply the remote explicitly (cumbersome). |
52 | 34 | neels | The gerrit repositories and git.osmocom.org are constantly synced, so it is sufficient |
53 | to clone from gerrit only. |
||
54 | 33 | neels | |
55 | h3. Simplest: new clone |
||
56 | |||
57 | 35 | neels | * Create a new clone from gerrit |
58 | * Fetch the commit hook that adds Change-Id to each commit to uniquely identify a commit |
||
59 | 33 | neels | <pre> |
60 | git clone ssh://$USERNAME@gerrit.osmocom.org:29418/$PROJECT.git |
||
61 | scp -P 29418 $USERNAME@gerrit.osmocom.org:hooks/commit-msg $PROJECT/.git/hooks/ |
||
62 | </pre> |
||
63 | |||
64 | h3. SSH config |
||
65 | |||
66 | In '~/.ssh/config', add these lines: |
||
67 | <pre> |
||
68 | Host foo |
||
69 | Hostname gerrit.osmocom.org |
||
70 | Port 29418 |
||
71 | User $USERNAME |
||
72 | </pre> |
||
73 | (replace 'foo' with your favorite shortcut name, |
||
74 | replace '$USERNAME' with your user name as used on the gerrit website) |
||
75 | |||
76 | Then you can shorten above commands to |
||
77 | 1 | zecke | <pre> |
78 | 33 | neels | git clone ssh://foo/$PROJECT.git |
79 | 35 | neels | scp foo:hooks/commit-msg $PROJECT/.git/hooks/ |
80 | 33 | neels | </pre> |
81 | |||
82 | h3. Add gerrit to an existing clone |
||
83 | |||
84 | 7 | neels | * Add the remote to be able to fetch and push to gerrit |
85 | * Fetch the commit hook that adds Change-Id to each commit to uniquely identify a commit |
||
86 | |||
87 | <pre> |
||
88 | USERNAME=gerrit_user_name |
||
89 | PROJECT=$(basename $PWD) |
||
90 | git remote add gerrit ssh://$USERNAME@gerrit.osmocom.org:29418/$PROJECT.git |
||
91 | scp -P 29418 $USERNAME@gerrit.osmocom.org:hooks/commit-msg .git/hooks/ |
||
92 | </pre> |
||
93 | |||
94 | 33 | neels | h2. Push for review |
95 | 1 | zecke | |
96 | 38 | neels | Checkout the revision or branch that you want to submit for review, then |
97 | |||
98 | 31 | neels | <pre> |
99 | 40 | neels | git push origin HEAD:refs/for/master |
100 | 1 | zecke | </pre> |
101 | 38 | neels | |
102 | 1 | zecke | You can optionally add a topic name with |
103 | 40 | neels | |
104 | <pre> |
||
105 | git push origin HEAD:refs/for/master/my_topic |
||
106 | </pre> |
||
107 | |||
108 | If you've added gerrit as a remote named 'gerrit', instead use: |
||
109 | 38 | neels | |
110 | <pre> |
||
111 | git push gerrit HEAD:refs/for/master/my_topic |
||
112 | </pre> |
||
113 | |||
114 | |||
115 | 1 | zecke | |
116 | 33 | neels | h2. Push a "private" user branch |
117 | |||
118 | *Note* that you must be a member of the "known users" group, see above. |
||
119 | |||
120 | If gerrit is your only remote, and if your local branch name is of the |
||
121 | form 'yourname/topic', you can just |
||
122 | 1 | zecke | <pre> |
123 | 33 | neels | git push |
124 | 1 | zecke | </pre> |
125 | 33 | neels | (and git will tell you what to do) |
126 | 1 | zecke | |
127 | 33 | neels | If you have other remotes as well, do |
128 | 1 | zecke | <pre> |
129 | 33 | neels | git push gerrit |
130 | 31 | neels | </pre> |
131 | 7 | neels | |
132 | 33 | neels | To push with a "nonstandard" local branch name, do |
133 | <pre> |
||
134 | git push gerrit HEAD:refs/heads/$USERNAME/topic |
||
135 | </pre> |
||
136 | 39 | neels | (If gerrit is your only remote, use 'git push origin ...' instead) |
137 | 33 | neels | |
138 | h2. List changesets in gerrit |
||
139 | 39 | neels | |
140 | If gerrit is your only remote: |
||
141 | |||
142 | <pre> |
||
143 | git ls-remote origin changes/* |
||
144 | </pre> |
||
145 | |||
146 | or, if you've added gerrit as a second remote: |
||
147 | |||
148 | 7 | neels | <pre> |
149 | git ls-remote gerrit changes/* |
||
150 | 2 | zecke | </pre> |
151 | 12 | msuraev | |
152 | 17 | neels | h1. Tips and Tricks |
153 | 1 | zecke | |
154 | 17 | neels | h2. Throw-away branch |
155 | |||
156 | If you need to adjust and re-submit patches, it may be handy to create a throw-away branch ("R D" in magit-gerrit in emacs for example), |
||
157 | make your changes/amendments and than send patch(es) back to gerrit while removing temporary branch automatically with "git review -f". |
||
158 | 13 | neels | |
159 | 25 | neels | h2. Re-submit a Branch with Amended Commits |
160 | 13 | neels | |
161 | 1 | zecke | On a feature branch, one typically has numerous commits that depend on their preceding commits. |
162 | 29 | neels | Often, some of the branch commits need to be amended for fixes. But, Gerrit will refuse your branch |
163 | re-submission if the first branch commit is unchanged. |
||
164 | 1 | zecke | |
165 | 16 | neels | To re-submit a branch, make sure to cosmetically tweak the branch's first commit log message |
166 | 22 | neels | before each re-submission (keep the Change-Id, really make just a cosmetic change). |
167 | 13 | neels | |
168 | 16 | neels | <pre> |
169 | git rebase -i master |
||
170 | # replace the first line's 'pick' with 'r' (or 'reword'), exit editor |
||
171 | # git presents you with commit log message, make any tiny modification. |
||
172 | 1 | zecke | </pre> |
173 | |||
174 | 29 | neels | The cause: Gerrit refuses to accept a commit with a Change-Id that it already knows and |
175 | where the commit hash is identical. |
||
176 | 1 | zecke | |
177 | 29 | neels | If you just cosmetically tweak the first commit's log message, the commit hash |
178 | is changed. Since the following commits contain their predecessor's commit hash, now |
||
179 | all of the branch's commit hashes are modified, and gerrit happily accepts them as a |
||
180 | new patch set. It will still pick up the Change-Ids (which you shouldn't edit) and |
||
181 | notice if commits have remained identical (keeping the votes). But with the minor |
||
182 | commit log tweak, it will no longer thwart your re-submission with an error message. |
||
183 | |||
184 | Note: you could modify all the Change-Ids, but now your branch submission would |
||
185 | open entirely new review entries and you would have to abandon your previous submission. |
||
186 | Comments on the first submission are lost and you cannot diff between patch sets. |
||
187 | |||
188 | |||
189 | 26 | neels | h2. Re-submit Previously Abandoned Changes |
190 | 16 | neels | |
191 | You have to edit the Change-Ids, on a branch that would be every single commit log message. |
||
192 | |||
193 | 13 | neels | <pre> |
194 | 1 | zecke | cd openbsc |
195 | git co my-branch |
||
196 | git rebase -i master |
||
197 | # replace all 'pick' with 'r' (or 'reword'), exit your editor |
||
198 | 13 | neels | # git presents each commit log message for editing |
199 | </pre> |
||
200 | |||
201 | 27 | neels | h2. Submit a "private" branch for master |
202 | 21 | neels | |
203 | If you've pushed a branch to refs/heads/* somewhere, gerrit will already know the Change-Ids on it. |
||
204 | 24 | neels | Make sure the option [[Gerrit#Private-Branches-Create-a-new-change-for-every-commit|Create a new change for every commit not in the target branch]] is _TRUE_ for your project, |
205 | 21 | neels | or gerrit will refuse to accept your submission. |
206 | |||
207 | 16 | neels | h1. Reasons for Particular Configuration |
208 | 13 | neels | |
209 | 16 | neels | h2. Rebase if necessary |
210 | |||
211 | There are different merge strategies that Gerrit performs to accept patches. |
||
212 | 13 | neels | Each project can be configured to a specific merge strategy, but unfortunately you can't |
213 | decide on a strategy per patch submission. |
||
214 | |||
215 | It seems that the "Merge if Necessary" strategy is best supported, but it creates non-linear |
||
216 | history with numerous merge commits that are usually not at all necessary. |
||
217 | |||
218 | Instead, the "Cherry Pick" strategy puts each patch onto current master's HEAD to create |
||
219 | linear history. However, this will cause merge failures as soon as one patch depends on |
||
220 | another submitted patch, as typical for a feature branch submission. |
||
221 | |||
222 | 1 | zecke | So we prefer the "Rebase if Necessary" strategy, which always tries to apply your patches to |
223 | 13 | neels | the current master HEAD, in sequence with the previous patches on the same branch. |
224 | However, some problems still remain, including some bugs in "Rebase if Necessary". |
||
225 | 1 | zecke | |
226 | 13 | neels | There's a problem with "Rebase if Necessary": If your branch sits at master's HEAD, Gerrit |
227 | refuses to accept the submission, because it thinks that no new changes are submitted. |
||
228 | This is a bug in Gerrit, which holger has fixed manually in our Gerrit installation: |
||
229 | 1 | zecke | |
230 | https://bugs.chromium.org/p/gerrit/issues/detail?id=4158 |
||
231 | |||
232 | |||
233 | 16 | neels | h2. Private Branches: Create a new change for every commit... |
234 | 1 | zecke | |
235 | 13 | neels | Say you have an extensive feature in development, and you want to keep it on the |
236 | upstream git repository to a) keep it safe and b) collaborate with other devs on it. |
||
237 | 16 | neels | So, of course, you have regularly pushed to refs/heads/yoyodyne/feature. |
238 | 13 | neels | |
239 | Since you have the gerrit commit hook installed, your feature branch already has |
||
240 | Change-Id tags in all commit log messages. |
||
241 | |||
242 | Now your feature is complete and you would like to submit it to master. |
||
243 | Alas, Gerrit refuses to accept your patch submission for master, because it |
||
244 | knows the Change-Ids are also on a different branch. |
||
245 | |||
246 | 16 | neels | Gerrit by default enforces that a Change-Id must be unique across all branches, |
247 | so that each submission for review is separate for each branch. Instead, we |
||
248 | want to handle Change-Ids per-branch, so that you can have the same change |
||
249 | submitted to different branches, as separate patch submissions, without having |
||
250 | to cosmetically adjust the Change-Id. |
||
251 | 13 | neels | |
252 | 16 | neels | Solution: set the option |
253 | _Create a new change for every commit not in the target branch_ to _TRUE_ |
||
254 | 13 | neels | |
255 | 20 | neels | h2. Allow content merges |
256 | 14 | neels | |
257 | By default, gerrit compares patches only by the files' paths. If two paths are the same, |
||
258 | it immediately shows them as conflicts (path conflicts). |
||
259 | |||
260 | In software development, a conflict usually means an actual content conflict, so if the |
||
261 | edits are in two entirely separate places in the file, we don't consider this a conflict. |
||
262 | |||
263 | 23 | neels | By setting _Allow content merges_ to _TRUE_ in the git project config, we tell Gerrit to |
264 | 14 | neels | perform text merges of the submitted patches and only complain about actual content |
265 | conflicts, in the usual software engineering sense. |
||
266 | 32 | neels | |
267 | h1. Admin |
||
268 | |||
269 | h2. Adding users to groups |
||
270 | |||
271 | Normally, the gerrit UI auto-completes a user name in the edit field. It has happened |
||
272 | though that an existing user is not auto-completed, as if it didn't exist. In that case, |
||
273 | find out the user ID (seven digit number like 1000123) and just enter that. |
||
274 | |||
275 | The user ID can be found on the user's "Settings" page, or in the database (s.b.). |
||
276 | |||
277 | h2. Querying the database directly |
||
278 | |||
279 | If your user has permission to access the database, you can place SQL queries using the |
||
280 | 'gerrit gsql' commands over ssh: |
||
281 | |||
282 | <pre> |
||
283 | ssh -p 29418 $USERNAME@gerrit.osmocom.org 'gerrit gsql --format PRETTY -c "show tables"' |
||
284 | ssh -p 29418 $USERNAME@gerrit.osmocom.org 'gerrit gsql --format PRETTY -c "select full_name,account_id from accounts"' |
||
285 | </pre> |
||
286 | |||
287 | This seems to be the MySQL dialect. |