[Development] gerrit : using branches (was: pointers to use it cleverly/efficiently?)

Welbourne Edward edward.welbourne at theqtcompany.com
Wed Mar 30 14:54:30 CEST 2016

René J.V. Bertin said:
> I've got a few things I'd like to put up for code review, which I've
> been putting off because I can only think of doing them either one by
> one (carrying each to completion before moving on to the next) or by
> using parallel working copies. Neither is what I'd call efficient, and
> I'm sure there must be a more clever way to achieve the same thing,
> possible involving git branches for instance.

In principle you don't actually need branches; you can work in a
"detached head" state (which git lectures you about, but you can
probably suppress that with a config option or the -q flag I'll use
below), e.g. after making some changes on your local dev,

$ git checkout -q gerrit/dev
$ git cherry-pick single-sha1-from-local-dev
# sort out any conflicts, test, review locally
$ git push gerrit HEAD:refs/for/dev

You can equally do this using a tmp branch,

$ git checkout -b tmp gerrit/dev
$ git cherry-pick ...
$ git push gerrit tmp:refs/for/dev
$ git reset --hard gerrit/dev
$ git cherry-pick ... etc.

which can be helpful if some of your commits are dependent on one
another and you want to gather them together, review and test locally,
fixup (rebasing to squash the fixes into the commit that made them
necessary, etc.), rinse and repeat, before pushing to gerrit.  This is
halfway to using topic branches.  Once you're done, it's tidy to

$ git branch -D tmp

Personally, I do my development on topic branches so that my dev, 5.7,
5.6 are pristine images of upstream.  The topic branch names also help
me keep track of what each one is about.  I put unrelated changes on
separate branches.  If I find I've mixed changes on a branch that I
later want to separate, I'll first rebase -i to shuffle their order so
there's an early part of the branch that's one group of changes (ending
with early-tip-sha1 below) and the rest is the other.  Then

$ git branch early-part-name early-tip-sha1
# That created a branch, leaving you still on old-mixed-branch;
# skip the next two if old-mixed-branch is a good name for the late part:
$ git checkout -b late-part-name old-mixed-branch
$ git branch -d old-mixed-branch
# Now separate the late part from the early:
$ git rebase early-part-name -onto dev

That last part, a rebase with -onto, picks up everything after the early
part - i.e. the whole late part, without the early part - and replays it
on top of dev, transforming

dev      early-part-name
|        |
v        v
o--A--B--C--W--X--Y--Z <- late-part-name

(early points to C, in case formatting got messed up !) into

o--A--B--C <- early-part-name
  W--X--Y--Z <- late-part-name

It's best to do such major branch surgery *before* pushing anything
involved to Gerrit - and, if doing so after, for the first push of the
rearranged changes, to make no changes *but* this rearrangement and let
reviewers know about it, since they can't usefully compare earlier patch
sets with later ones.  Combining real changes to your patch set with
rebasing is unkind to reviewers - keep rebases clean, when you need to
do them, and let reviewers know about them.

If I just want to select take a few commits from an existing branch to
send for early review, I'll typically use a tmp branch as described
above.  It's also possible to use a tmp branch to check several separate
branches do all play nicely together:

$ git checkout -b tmp last-branch
$ git rebase penultimate-branch
$ git rebase second-branch
$ git rebase first-branch
# build test, etc.

which shall teach you about conflicts along the way.  Just remember that
any changes you make on tmp aren't reflected on the original branches
until you cherry-pick them back there (and optionally rebase to put them
where they belong).


More information about the Development mailing list