NAME
git-gerrit - Git extension to implement a Gerrit workflow
VERSION
version 0.012
SYNOPSIS
git gerrit new [--update] TOPIC [BRANCH]
git gerrit push [--keep] [--force] [--[no]rebase] [--draft] [--submit] \
[--base BASE] [--topic TOPIC] [--reviewer USER] [--cc USER]
git gerrit query [--limit LIMIT] [--verbose] [[NAME=]QUERY]*
git gerrit my [--limit LIMIT] [--verbose] [changes|drafts|watched|starred]
git gerrit show [CHANGE]
git gerrit checkout [CHANGE]
git gerrit upstream [--keep]
git gerrit cherry-pick [OPTIONS]* CHANGE
git gerrit reviewer [--add USERS] [--confirm] [--delete USERS] [CHANGE]
git gerrit review [--message TEXT] [--keep] [[LABEL]=VOTE]* [CHANGE]
git gerrit abandon [--message TEXT] [--keep] [CHANGE]
git gerrit restore [--message TEXT] [CHANGE]
git gerrit revert [--message TEXT] [CHANGE]
git gerrit submit [--no-wait-for-merge] [--keep] [CHANGE]
git gerrit config
git gerrit version
DESCRIPTION
Git-gerrit is a Git extension to manage changes using Gerrit Code Review.
Git-gerrit offers a rich set of sub-commands to make it easy to create, query, amend, review, and submit changes to Gerrit, making it possible to interact with it through the command-line, avoiding its web interface most of the time and improving your efficiency. The goal is to make Gerrit's review process feel like a natural extension of Git.
Git-gerrit provides three main features:
An easy and safe way to push changes to Gerrit through the git gerrit push sub-command, avoiding the need to type remote names and long refspecs.
A standard way to map Gerrit changes into local branches, referred to as "change-branches", making it easier to manage several changes simultaneously and to perform the fetch-amend-push review cycle.
Several sub-commands to query and inspect Gerrit changes and also to review and submit them.
Git-gerrit is implemented on top of Gerrit's REST API, which was consolidated in its version 2.6. As this API matures, expect git-gerrit to incorporate new functionality.
There are a few alternatives to git-gerrit described below.
INSTALLATION
Git-gerrit requires Perl 5.10 or newer and Git (any version should do, but 1.8 is better integrated). Check it like this:
perl -v
git --version
Git-gerrit is part of the App::GitGerrit distribution that you have to download from CPAN and install. There are a few ways to do it, depending on your environment. Here are a few tips:
If you cook your own Perl
If you build your own Perl, perhaps using perlbrew, you know the drill:
cpanm App::GitGerrit
Ubuntu or Debian?
If you want to use the Perl that comes packaged in your Debian-based distribution, you can install some git-gerrit dependencies from packaged perl modules. This are the ones packaged with Ubuntu 12.04:
sudo apt-get install -y \
libfile-slurp-perl liburi-encode-perl libhtml-tree-perl libjson-perl \
libscope-guard-perl libcrypt-ssleay-perl libwww-perl cpanminus
The nifty cpanm
installer should take care of the remaining dependencies and of installing git-gerrit
for you like this:
sudo su -l -c "cpanm App::GitGerrit"
RedHat or CentOS?
If you want to use the Perl that comes packaged in your RedHat-derived distribution, you can install some git-gerrit dependencies from packaged perl modules. This are the ones packaged with CentOS 6.4:
sudo yum install -y \
perl-File-Slurp perl-URI perl-HTML-Tree perl-JSON perl-Scope-Guard \
perl-Test-Exception perl-Test-use-ok perl-Crypt-SSLeay perl-YAML \
perl-CPAN perl-ExtUtils-MakeMaker
The verbose cpan
installer should take care of the remaining dependencies and of installing git-gerrit
for you like this:
sudo su -l -c "cpan App::GitGerrit"
Windows
On Windows I suggest that you install Strawberry Perl. Then, open a command line tool and type this:
cpanm Data::Util App::GitGerrit
Note that on Windows you may have to invoke git-gerrit
directly as git-gerrit and not through Git as git gerrit. This is because Git will probably use the old Perl that comes bundled with it, not Strawberry Perl. Your mileage may vary, though.
CONFIGURATION
You must tell git-gerrit how to interact with your Gerrit server by defining a few configuration variables in Git's git-gerrit
configuration section. All these variables are required. If they aren't set, git-gerrit will provide a helpful message telling you how to set them up.
git-gerrit.baseurl
The base URL of your Gerrit server. This usually can be configured globally, if you have a Gerrit server hosting several of your repositories. It's a good idea to insert your username into this URL to avoid being asked for it interactively.
git-gerrit.project
The project name associated with your repository.
git-gerrit.remote
The Git remote name you use to push commits to and fetch commits from your Gerrit server.
The following configuration variables may be used to change git-gerrit's default operation.
git-gerrit.reviewers USERS [CONDITION]*
This variable specifies a list of Gerrit users to be automatically invited as reviewers in a git gerrit push command.
USERS is a colon-separated list of usernames.
CONDITIONs are space-separated boolean expressions. All CONDITIONs, if any, must be true for USERS to be invited. If no CONDITIONS are specified, USERS are invited.
A CONDITION may check either the name of the branch to which the change is being pushed or the names of the files affected by the change itself. The matching may be either exact or by regular expressions, as follows.
branch=REFNAME
Checks if REFNAME is exactly equal to the change's upstream name (without the
refs/heads
prefix).branch~REGEXP
Checks if the upstream name matches REGEXP.
path=PATH
Checks if the path of any file affected by the commit being pushed, as shown by
git diff --name-only upstream..HEAD
is exactly equal to the complete path of one of those files.path~REGEXP
Checks if the path of any affected file matches REGEXP.
You may specify the
git-gerrit.reviewers
variable multiple times. All users mentioned in all specifications that match their CONDITIONs are invited as reviewers to the current change being pushed.
AUTHENTICATION
If you have Git 1.8.0 or later, git-gerrit uses Git's credential management system via its git-credential command to obtain credentials for connecting to Gerrit. You can take advantage of this by configuring Git's credential.helper
variable to use a persistent credential storage and avoid being asked for the authentication credentials repeatedly. Please, read gitcredentials manpage to know how to configure this system. But here are a few tips anyway:
On Ubuntu Linux (tested on 13.04)
Use the git-credential-gnome-keyring program which provides a very nice integration with your desktop environment. You have to compile the helper first:
sudo apt-get install libgnome-keyring-dev sudo make -C /usr/share/doc/git/contrib/credential/gnome-keyring git config --global credential.helper /usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring
On other Unix-like systems
The git-credential-cache command which comes with Git is as a balanced compromise between convenience and security:
git config --global credential.helper cache --timeout 86400
On Windows systems
The best choice seems to be the third-party application git-credential-winstore, which you have to install first.
git config --global credential.helper winstore
If you're using a pre-1.8 Git that doesn't support the git-credential command, there are a few fall-backs.
First, git-gerrit tries to get credentials from the git-gerrit.baseurl
configuration variable. The URL should be in a format like https://username:password@host/path
. Security conscious people should avoid putting credentials there, but if you do git-gerrit will be satisfied.
Then, git-gerrit tries to load Perl's Net::Netrc module, if available, to get credentials from a netrc(5) file.
As a last resort, git-gerrit tries to load Perl's Term::Prompt module to prompt you for the credentials.
If none of this works, git-gerrit dies screaming.
GLOSSARY
There are a few concepts that should be clear in order to the sub-commands documentation below to make sense.
- change
-
Each commit pushed to one of Gerrit's virtual branches (
refs/for
orrefs/drafts
) creates achange
for review. - Change-Id
-
A Change-Id is a 40-hexadecimal characters long SHA-1 hash prefixed with an
I
. It uniquely identifies a change and is normally generated by thecommit-msg
hook and inserted in the commit message footer. - {change-id}
-
A {change-id}, is a more general identifier used by Gerrit's REST API to uniquely identify a change . It can be expressed in one of three forms:
As an ID of the change in the format "<project>~<branch>~<Change-Id>", where, for the branch, the
refs/heads/
prefix can be omitted (e.g.,myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940
).As a
Change-Id
if it uniquely identifies one change (e.g.,I8473b95934b5732ac55d26311a706c9c2bde9940
).As a legacy numeric change ID (e.g.,
4247
).
You may pass any form of change-id to git-gerrit's sub-commands when they require a CHANGE argument. Most commonly, you'll be using the legacy numeric ID, just because it's more convenient.
- upstream branch
-
You normally should avoid creating changes directly on a local tracking branch. Instead, you should create a local topic branch deriving from the tracking branch to work on each change. We refer to the tracking branch from which your topic branch derived as the topic's
upstream branch
. - change-branch
-
A
change-branch
is a local branch with a special name that git-gerrit creates and maps to a Gerrit change.When the sub-command
git gerrit new TOPIC BRANCH
starts a new change it creates a topic branch named change/BRANCH/TOPIC, which we call a change-branch. We refer to BRANCH as the change-branch'supstream
, because it is the branch from which the change-branch derives and to which it will be ultimately merged back again.When
git gerrit checkout CHANGE
fetches an existing change it creates a change-branch named change/BRANCH/ID, where BRANCH is the name of the branch associated with the change, and ID is its legacy numeric change ID.So, you should reserve the
change/
top-level branch name for the change-branches managed by git-gerrit.
SUB-COMMANDS
Each git-gerrit sub-command has its own set of options, described in its own section below.
The options below, however, are accepted by all of them:
- --debug
-
This option makes git-gerrit print to STDERR every system command (usually a Git command) invoked and every Gerrit REST call made during the execution of its sub-commands. System commands are prefixed with CMD: and Gerrit REST calls with GERRIT:.
- --help
-
Shows git-gerrit's manpage and quits.
Options names may be abbreviated to uniqueness, case does not matter, and a single dash is sufficient, even for long option names.
git gerrit new [--update] TOPIC [BRANCH]
The new
sub-command starts a new change on top of the current branch or BRANCH, if specified. It creates a new change-branch off of BRANCH called change/BRANCH/TOPIC
and checks it out for you to start making changes to your working area.
The TOPIC name must contain at least one non-digit character so that it's clear that this is a new change-branch, not yet pushed to Gerrit. Also, the TOPIC name cannot contain slashes so that it's not confused with the branch name. It's usually best to use only letters and hyphens.
- --update
-
This option makes git-gerrit update BRANCH before creating the change-branch by fetching from Gerrit and fast-forward-merging it with its remote branch. This way you guarantee to start a change on top of the newest state of your project, which is usually the right thing to do.
You will be warned if your working area is dirty, as this is sometimes a mistake.
git gerrit push [--keep] [--force] [--[no]rebase] [--draft] [--submit] [--base BASE] [--topic=TOPIC] [--reviewer USERS] [--cc USERS]
The push
sub-command should be invoked to push a change-branch to Gerrit's refs/for/
branch associated with its upstream branch. It should be invoked when you have the change-branch checked out in your working area.
When a new change-branch is pushed it creates a Gerrit change associated with the TOPIC in its name, as created by git gerrit new
above.
After a successful push, git-gerrit checks out the upstream branch and deletes the original change-branch. The goal is to maintain a clean namespace, containing only the change-branches that are being worked on. When you push one to Gerrit, you don't need to keep it any longer locally. If you need to amend it later, you'll be able to get to it with the git gerrit checkout
sub-command.
- --keep
-
This option tells git-gerrit not to checkout the upstream and not to delete the change-branch, keeping your working area intact.
- --force
-
By default, git-gerrit refuses to push a change-branch if it contains more than one commit dangling from its upstream. It's best to avoid multiple commit pushes, because if you have to amend them later, having multiple commits may require rebasing dependent commits, which is a more complex operation and clutters the review history of the change.
This option makes git-gerrit perform multiple commit pushes without complaining.
- --[no]rebase
-
Before a brand new change-branch (one ending in a TOPIC
name
) is pushed, its upstream branch is updated and it is rebased on top of its upstream. This is to make sure you're pushing a change based on the newest project state. If, by any reason, you don't want to have it rebased, use the--norebase
option.A change-branch that has been checked out (one ending in an ID) 't rebased by default, because this would clutter the change review history in Gerrit. If you want it rebased nonetheless, use the
--rebase
option. - --draft
-
This option makes git-gerrit push the change-branch to
refs/drafts/UPSTREAM
instead of torefs/for/UPSTREAM
, creating a draft change in Gerrit. - --submit
-
This option tells Gerrit to auto-merge the change during push, which is a feature implemented in Gerrit 2.7.
- --base BASE
-
This option selects a new merge base for Gerrit, which is a feature implemented in Gerrit 2.7.
- --topic TOPIC
-
This option specifies another name for the topic that will be associated with the change. By default, the topic name is the last component of the current change-branch name, as specified by the
git gerrit new
sub-command. - --reviewer USERS
-
This option let's you invite a list of users to review your change.
USERS is a colon-separated list of usernames. You may also pass this option more than once, to invite more than a set of users.
- --cc USERS
-
This option let's you notify a list of users about your change.
USERS is a colon-separated list of usernames. You may also pass this option more than once, to invite more than a set of users.
git gerrit query [--limit LIMIT] [--verbose] [[NAME=]QUERY]*
The query sub-command let's you list Gerrit changes meeting specific criteria. The matching changes are shown in tabular format, one change per line, listing their legacy ID, status, Code-Review vote, time of last update, project name, branch name, owner name, and subject line.
You may pass a list of queries. Each QUERY's results is presented separated from the other by a empty line and a header containing the query's name and expression inside brackets. For example:
$ git gerrit query 'Starred changes=is:starred' is:draft
[Starred changes=is:starred]
ID STATUS CR UPDATED PROJECT BRANCH OWNER SUBJECT
1186 MERGED +2 2013-09-18 helloworld master Gustavo Chaves [SB-1] Test amend 3
[QUERY=is:draft]
ID STATUS CR UPDATED PROJECT BRANCH OWNER SUBJECT
1187 NEW 2013-09-08 helloworld master Gustavo Chaves [SB-2] Make foo
Note that unnamed queries are prefixed by QUERY=
instead of by their names.
Each QUERY can be specified by a Gerrit search expression.
- --limit LIMIT
-
This option put a limit on the number of changes that are shown for each QUERY.
- --verbose
-
This option makes the change topic be shown inside parenthesis to the right of the change branch name. This requires a separate REST call for each change, making the result appear more slowly.
git gerrit my [--limit LIMIT] [--verbose] [changes|drafts|watched|starred]
The my sub-command provides a set of pre-defined queries for the query sub-command. It's based on Gerrit's standard queries shown in its web interface under the My
tab.
The changes
argument is used by default if you don't specify any.
The options taken by the my
sub-command are passed to the query
sub-command.
git gerrit show [CHANGE]
The show sub-command describes a CHANGE in detail, showing much like what Gerrit shows in a change page of its web interface. For example:
$ git gerrit show 1186
Change-Num: 1186
Change-Id: I0bb976fe1890657d7a1c3ba403e0b58ac2b63cd7
Subject: [SB-1] Test amend 3
Owner: Gustavo Chaves
Project: helloworld
Branch: master
Created: 2013-09-18 16:22:21
Updated: 2013-09-18 19:45:56
Status: MERGED
If a CHANGE is not passed the branch associated with the current change-branch is described. If you're not in a change-branch, you'll get an error.
git gerrit checkout [CHANGE]
The checkout sub-command fetches a CHANGE from Gerrit, creates a change-branch pointing to it and checks it out, leaving your working area in the CHANGE state.
A Gerrit change may contain a series of patch-sets. The checkout
fetches the current (latest) one. If there is already a change-branch for the change, it will be updated to the change's current patch-set.
If you omit the CHANGE argument and you are in a change-branch, it will be updated with its current patch-set.
The shorter name co
can also be used instead of checkout
.
git gerrit upstream [--keep] [--delete]
The upstream sub-command should be invoked when you're in a change-branch. It checks out the upstream branch and deletes the change-branch if it's associated with an already pushed change, i.e., if its name ends in a legacy numeric id, not in a topic name.
The shorter name up
can also be used instead of upstream
.
- --keep
-
This option prevents the change-branch deletion after the upstream checkout.
- --delete
-
This options forces the change-branch deletion when it's a new change. However, the <--keep> option has precedence, meaning that if both options are present the change-branch isn't deleted.
git gerrit cherry-pick [OPTIONS]* CHANGE
The cherry-pick sub-command fetches CHANGE from Gerrit and applies it to the current branch using the git cherry-pick
command. The CHANGE id is required and every OPTION (but --debug) is passed as-is to the git cherry-pick
command. You should read git-cherry-pick manpage to know what options are available. Some of the most usefull ones are these: -e, -x, and -n.
The shorter name cp
can also be used instead of cherry-pick
.
git gerrit reviewer [--add USERS] [--confirm] [--delete USERS] [CHANGE]
The reviewer sub-command allows you to manage the list of reviewers for a CHANGE. You can omit the CHANGE argument if you're in a change-branch. In this case, you'll be managing the associated change reviewers.
- --add USERS
-
This option let's you invite new users to review the change. You can pass a comma-separated list of users and even use more than one
--add
option.You can use Gerrit groupnames in addition to usernames, if you want to invite a group of users to review.
- --confirm
-
Gerrit may reject the addition of groups with too many users because it recons you may be doing it by mistake. In this case, you'll receive an error message something like this:
"The group My Group has 15 members. Do you want to add them all as reviewers?"
If you really want to invite them all, try again with using the
--confirm
option. - --delete USERS
-
This option let's you remove reviewers from the change. You can pass a comma-separated list of users and even use more than one
--delete
option.You can use Gerrit groupnames in addition to usernames, if you want to remove a group of reviewers.
After adding and removing reviewers, git gerrit reviewers
shows the remaining list of reviewers of the CHANGE.
git gerrit review [--message TEXT] [--keep] [[LABEL]=VOTE]* [CHANGE]
The review sub-command allows you to review (duh!) a CHANGE by casting votes and adding messages to it.
You can omit the CHANGE argument if you are in a change-branch, in which case you'll be reviewing the associated change. In this case, after a successful review, the change-branch will be deleted and its upstream checked out.
You can cast multiple votes using LABEL=VOTE
arguments, where LABEL names a Gerrit label and VOTE is a negative, zero, or positive number. If you omit the LABEL name (but not the equal sign!) you'll be voting in the standard Code-Review
label.
The Git editor (see the definition of GIT_EDITOR
with the git help var
command) is invoked for you to compose a message to be added to the review.
- --message TEXT
-
This option adds a message to the review avoiding the Git editor invocation.
- --keep
-
This option avoids the change-branch deletion after a successful review.
git gerrit submit [--no-wait-for-merge] [--keep] [CHANGE]
The submit sub-command submits an approved CHANGE, making Gerrit merge it into its remote upstream branch.
You can omit the CHANGE argument if you are in a change-branch, in which case you'll be submitting the associated change. In this case, after a successful submission, the change-branch will be deleted and its upstream checked out.
- --no-wait-for-merge
-
By default git-gerrit will wait for the merge of the change into its branch to complete in Gerrit. This option tells it not to wait and finish as soon as it receives Gerrit's submit acknowledge.
- --keep
-
This option avoids the change-branch deletion after a successful submission.
git gerrit abandon [--message TEXT] [--keep] [CHANGE]
The abandon sub-command abandons an unmerged CHANGE.
You can omit the CHANGE argument if you are in a change-branch, in which case you'll be abandoning the associated change. In this case, after a successful abandonment, the change-branch will be deleted and its upstream checked out.
The Git editor (see the definition of GIT_EDITOR
with the git help var
command) is invoked for you to compose a message to be added to the action.
git gerrit restore [--message TEXT] [CHANGE]
The restore sub-command restores an abandoned CHANGE.
You can omit the CHANGE argument if you are in a change-branch, in which case you'll be restoring the associated change.
The Git editor (see the definition of GIT_EDITOR
with the git help var
command) is invoked for you to compose a message to be added to the action.
git gerrit revert [--message TEXT] [CHANGE]
The revert sub-command reverts an already merged CHANGE. Gerrit does so by creating, in the server, a new change with an inverted patch on top of the CHANGE remote upstream branch.
You can omit the CHANGE argument if you are in a change-branch, in which case you'll be reverting the associated change.
The Git editor (see the definition of GIT_EDITOR
with the git help var
command) is invoked for you to compose a message to be added to the action.
git gerrit config
The config sub-command lists Git's configuration variables in the git-gerrit
section. It's just a shortcut to
git config --get-regexp "^git-gerrit\."
git gerrit version
The version sub-command shows the versions of git-gerrit, Git, and Gerrit that you're using.
COMMIT-MSG HOOK
Gerrit provides a commit-msg
hook for Git that should be installed in your repositories. Its purpose is to insert a Change-Id
footer in the commit messages so that Gerrit can discern independent commits from merely amended ones.
Git-gerrit takes care of installing this hook for you. When you invoke its new
or push
sub-commands, it checks to see if your repository already has a commit-msg
hook installed. If not, it automatically downloads Gerrit's standard hook and installs it for you.
GERRIT WORKFLOW
Here are the main use-cases of git-gerrit to manage your changes.
Creating a new change for review
Suppose you want to create a new change on master:
git gerrit new topic master
# edit
git commit
git gerrit push
First you create a new change-branch for your new change. If you're already in master you don't need to mention it on the first line. Then you make your change editing your working area and committing. When you're done, simply tell git-gerrit to push your change and get back to master.
In order to do the same thing using only standard Git commands you'd do something like this:
git checkout master
git pull --ff-only
git checkout -b change/master/topic
# edit
git commit
git push origin HEAD:refs/for/master
git checkout master
git branch -D change/master/topic
Reviewing a change
git gerrit my changes
git gerrit checkout 1234
git show
git gerrit review =-1
First, if you don't know the {change-id}
of the change you want to review, you ask my changes
to get a list of the changes still unreviewed. Then you checkout one change and study it. Finally, you record your review and gets back to the change's upstream branch.
Without git-gerrit you'd have to perform the review using Gerrit's web interface.
Amending a change
git gerrit checkout 1234
# edit
git commit --amend
git gerrit push
To amend a change you first check it out to a local change-branch. Then you can amend it and, finally, push it as another patch-set to Gerrit, checking out upstream again.
Without git-gerrit you would have to go first to Gerrit's web interface, find the change, and copy its fetch/checkout command line. Then you could paste it in your terminal and perform the amending like this:
git fetch https://gustavo@gerrit.example.net/project refs/changes/90/1190/2 && git checkout FETCH_HEAD
# edit
git commit --amend
git push origin HEAD:refs/for/master
git checkout master
SEE ALSO
There are some alternatives to git-gerrit, other Git extensions to make it easier to interact with Gerrit. The three mentioned below are the most well known. All of them use Gerrit's mature and simple SSH API while git-gerrit's distinguishes from them in that it uses Gerrit's newer and more comprehensive REST API.
-
Being the original inspiration for git-gerrit, git-review is a mature tool that's used by some very well known projects, such as OpenStack, MediaWiki, and LibreOffice.
-
Simpler than git-review, git-change is better documented and has the best name of all. From it, git-gerrit took the change-branch concept.
-
A very simple tool to query Gerrit and make it easier to push changes.
If you're interested in Gerrit automation per se, you can take a look at the Gerrit::REST Perl module, which is used by git-gerrit
to interact with Gerrit via it's REST API.
AUTHOR
Gustavo L. de M. Chaves <gnustavo@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by CPqD <www.cpqd.com.br>.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.