You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 34 Next »

Gerrit is primarily a code inspection tool, but can also be used to track the status of patch as it is build tested, and finally merged to a branch. Developers submit patches to Gerrit using git, and there is a rich browser interface for performing inspections. Inspectors can also pull the change directly to their own repository and inspect the change locally.

To upload changes to Gerrit, you must first register and add an ssh key to your account. For details on setting up your Gerrit account and sending patches, please see the Gerrit documentation.

Gerrit can host many git repositories, and of course each of those repositories can contain many branches. For instance, these are some of the repositories on Gerrit today:

repo

description

status

fs/lustre-release

Whamcloud's Lustre for new releases

Gatekeeping in effect

 

branch: b1_8

for 1.8.6+ maintenance releases

Critical bug fixes only

 

branch: b2_1

for 2.1.0+ feature releases

Bug fixes only

 

branch: b2_2

for 2.2.0+ feature releases

Bug fixes only

 

branch: master

for 2.3.0+ releases

Open for new features and fixes

fs/lustre-dev

A collection of development branches for Whamcloud developers

no gatekeeping

tools/e2fsprogs

Mirror of kernel.org e2fsprogs, contains lustre branches

limited checkins

 

branch: master-lustre

for 1.41.90+ releases

Managing Changes in Git

Whole books could be written about this topic, and there plenty of online tutorials on the web that explain this in more detail and suggest other methods of managing changes. However, this distilled version is (hopefully) enough to get started.

To make an initial checkout of the master Lustre Git repository:

$ git clone -b master http://git.whamcloud.com/fs/lustre-dev.git lustre-master
$ cd lustre-master

Typically in git, one creates a new local branch for each change being made. The branch is created based on one of the local, pristine branches follow the main development branches, usually the master. A new local branch is usually create using checkout:

$ git checkout -b my-brilliant-idea master

This creates a new branch based on master called my-brilliant-idea, and also makes it the current branch.

In order ensure that the commit description contains the correct name and email address for you, it is possible to specify this directly to Git creating or modifying the $HOME/.gitconfig file in your home directory (preferred), or in the .git/config file in the local repository. This only needs to be done one time, or once per checkout, if done in the local repository.

[user]
        name = Random J. Developer
        email = random@developer.example.org

Now all git commits in any repository will use this name/email regardless of which user account is used to do the modifications, if using $HOME/.gitconfig file. If you want to specify a different name or email for a specific repository, it is possible to add this information to the .git/config file in that specific repository. See commit comment details below.

For Lustre patches, the both the code needs to follow specific code style guidelines, as do the commit comments for each patch. In order to help maintain the uniform code style, Lustre-specific Git commit hooks should be installed in all Lustre development trees. In the top-level directory of the checked-out Lustre repository install the hooks using:

ln -sf ../../build/commit-msg .git/hooks/
ln -sf ../../build/prepare-commit-msg .git/hooks/

This will run the build/prepare-commit-msg script from the currently-checked-out Lustre tree to run the modifications through the build/checkpatch.pl script for style errors, and the build/commit-msg script afterward to verify the format of the commit message itself.

Once you've made the change, and you're ready to create an inspection, you commit. Before you commit in Git, you need to identify which new or changed files you want to commit using git add <filename>. If you haven't added any new files, and you want to commit all the files that you have changed (which is the usual case), then you can use the -a option to commit:

$ git commit -av

This will put you into an editor to update your commit comment, and when you save it will commit the change locally. The -v option appends the diff to the edit buffer so you can review what is about to be committed. This is very useful to verify that you are committing what you want to commit, and not changes or files that are unrelated to the current change.

It is best to commit relatively frequently to keep your changes limited to a single fix. If you notice other, unrelated, issues that need to be fixed, then it's best to put them in a separate commit on a separate branch, so they can be submitted to Gerrit independently for inspection, testing, and landing. The stash command is handy for this:

# While fixing a bug you notice something evil that must be fixed.
# First set your current work aside:
$ git stash

# Next go create a new branch and purge the ugliness you just discovered:
$ git checkout -b my-eyes-are-bleeding master
\{ fix ugliness \}
$ git commit -av

# Now go back to what you were working on:
$ git checkout my-brilliant-idea
$ git stash pop
Formatting Git Commit Comments

Having good commit comments helps everyone that is working on the code. See Commit Comments for a detailed description of the commit comment style. If your commit does not include the Change-Id: line as described below, the patch will be automatically rejected at submission time.

Sample Commit message:

LU-nnn component: short description of change under 62 columns

A more detailed explanation of the change being made.  This can be
as detailed as you'd like, possibly several paragraphs in length.

Please provide a detailed explanation of what problem was solved,
a good high-level description of how it was solved, and which
parts of the code were affected (including function names as
needed, for easier searching).  Wrap lines at 70 columns or less.

Signed-off-by: Random J Developer <random@developer.example.org>
Change-Id: Ica9ed1612eab0c4673dee088f8b441d806c64932
Adding the Change-Id field

Gerrit requires all changes to have the Commit-Id: field, or it will be rejected. It should be added automatically by the .git/hooks/commit-comment script. See Commit Comments for a detailed description of the Commit-Id: field.

Creating Inspection Requests

An inspection request is created by pushing a change to a special branch on the Gerrit repository. To create an inspection request for a change in your local branch the local commit (or series of commits) needs to be pushed to the Gerrit review repository.

It is possible to push a series of dependent commits from a local branch in this same way, and each one will create a separate change in Gerrit. Patch series should be used to split complex code changes that are implementing a single larger feature into chunks that are easier to understand. These changes will be dependent on each other, so if one patch needs to be refreshed after an inspection it will cause all of the later patches to be refreshed also. That will clear all of the inspections and restart testing on all of the patches.

Patch series should not be used for code that was written and then had a series of bug fixes applied to it after local testing. The later (local) bug fixes should be squashed into the original change before submission. Note that each patch in a series must build and test properly before it can be landed, so intermediate bugs or compile warnings are not allowed.

If you have a series of independent commits to be reviewed, each one should be in a separate local branch and pushed separately to Gerrit. This allows the patches to be inspected, tested, and landed independently, and will avoid the overhead and delay of repeatedly inspecting, building, and testing patches that are only refreshed because of an earlier (unrelated) patch in a series being modified.

git push ssh://USER@review.whamcloud.com:29418/fs/lustre-release HEAD:refs/for/master

for the "master" branch of the lustre-release repo, or:

git push ssh://USER@review.whamcloud.com:29418/fs/lustre-release HEAD:refs/for/b1_8

for the "b1_8" branch of the lustre-release repo, or:

git push ssh://USER@review.whamcloud.com:29418/tools/e2fsprogs HEAD:refs/for/master-lustre

for the "master-lustre" branch of the e2fsprogs repo.

For convenience, you can add this to your ~/.ssh/config file:

Host review
  Hostname review.whamcloud.com
  Port 29418
  User \{YourUserid\}
  IdentityFile ~/.ssh/my-key-id_rsa

Creating an inspection request for a change against master (assuming the remote alias has been added to ssh config):

git push ssh://review/fs/lustre-release HEAD:refs/for/master

Creating an inspection request for a change against b1_8 (assuming the remote alias has been added to ssh config):

git push ssh://review/fs/lustre-release HEAD:refs/for/b1_8

And add a the Gerrit server as a remote to your git repository:

$ git remote add review ssh://review/fs/lustre-release
Automatically Build and Test

When the patch has been pushed to the Gerrit review repository, it will print a URL for that change set that should be added to the Jira ticket for tracking.

All patches submitted to Gerrit will be built automatically by Jenkins (formerly Hudson) with a number of configurations. Currently for the master branch this includes RHEL6 i686/x86_64 client/server, RHEL5 i686/x86_64 client, Ubuntu 10.04 x86_64 client, and SLES11 SP1 x86_64 client. The success/failure of these builds will be posted to the change in Gerrit.

After a successful build on all of the configurations, one of the configurations will be regression tested automatically, and a link to the test results in Maloo will be posted to Gerrit. It is also possible to post test results to Maloo from manual testing.

Requesting inspections

In order to actually get a patch landed, you need to request at least two inspections in Gerrit for the patch. This is done by visiting the Gerrit web page for the change (at the URL returned when the commit was pushed, or it can be found from the main page after logging in). Enter the email address for the inspectors and click the Add Reviewer button.

In conjunction with the two inspection requests, the patch has to successfully build on all supported architecture/distro combinations, and pass the automatic testing (as reported by Maloo).

Updating Inspection Requests

Gerrit makes it easy to update an inspection request with a new patch, and doing this allows inspectors to see differences between the patches so they only need to inspect the changes. Also, the original inline comments are maintained and moved to the new patches. The key to keeping updated inspection requests linked to the original patch is the Change-Id: field - this is what Gerrit uses to find the original patch to update.

A critical thing to point out is that you need submit a new version of the entire change - not just an update to the change.

One way of modifying an existing change is to apply the updates to your tree as usual and create a new commit (this time the commit message doesn't matter as you are about to change it). Then, merge the two changes using git rebase -i <parent-branch>. Interactive rebase will display a list of patches in an editor, and you can "squash" the the modifications to the patch in the new commit into the original patch. (See the help text in the commit message editor window for more information.) Then it will put you in an editor again to manually merge the two commit messages. Make sure you keep the original Change-Id: line, and delete the new one, and edit the commit messages so they're combined into a single commit. If you don't have a Change-Id: line in your commit message (because you didn't install the commit-msg hook, see Commit Comments) you can copy it from the top Gerrit web page for that change and paste it into the new commit message. Once the change is committed, push your branch to Gerrit again, and the original request will be updated with the new version of the patch.

The easiest way to update the most recent commit comment (which is often the one you want to update), is to use git commit --amend -a.

(Re-)Basing One Change on Another Change

It is possible to base a new change, or rebase an existing change, on an uncommitted patch in Gerrit. This might be useful if both changes are impacting the same code, and one change is clearly dependent on another for some reason, or if they will cause conflicts when merged and a decision is made to land them in a specific order. It is desirable to break a patch into multiple functionally-separate commits for several reasons, see Requirements for patch submission. If the patches are truly independent (i.e. no overlapping changes to the same files, no dependent functions, etc), then those patches should be submitted in separate branches, and this section does not apply.

If both patches are being developed by the same person, the easiest way to have a series of dependent changes is to commit them into separate patches order on the same branch. Then, when a change is made to any patch on that branch, all of the dependent changes will also be resubmitted to Gerrit so that they will be ready to land when the earlier patches are merged.

If updates need to be made to one of the patches, it should be merged into the original commit, rather than being an additional patch at the end of the series. This can be done by running git rebase -i <parent-branch>, then marking a particular patch for edit. That will cause the earlier patches in the series up to the to be applied, then stop for interactive editing/testing of that patch. Once the patch has been updated, run git add {modified files} to include the new updates into this patch, and git rebase --continue to merge the updates into the existing patch and continue the rebase process.

In the case where changes need to be based on a patch from another developer, it is possible to check out the desired patch from Gerrit using one of the supplied Git URLs in the Download section under the patchset. Select the checkout and Anonymous HTTP tags, then copy the URL and paste it into a working Lustre checkout, for example to fetch patchset 16 from http://review.whamcloud.com/1264, create a branch for it, and then create a new branch for your local changes based on that change, use:

[lustre]$ git fetch http://review.whamcloud.com/p/fs/lustre-release refs/changes/64/1264/16 && git checkout FETCH_HEAD
[lustre]$ git checkout -b b_1264
[lustre]$ git checkout -b b_my_changes

Any changes in the b_my_changes will be based on those of b_1264. When b_my_changes is pushed to Gerrit, it will have a dependency on change 1264, so it will not be able to land until change 1264 itself is landed.

Pushing a Git Tag

This is normally done by the branch maintainer, but is recorded here for future reference.

Switch to the branch you want to create a branch in (normally master or b1_8).

Create the tag with:

git tag -a TAG_NAME

then push it upstream with

git push TAG_NAME

Note, this requires certain privileges on the server. If review is a secondary server for your repository, use

git push review TAG_NAME
  • No labels