sorin
sorin

Reputation: 170598

How to always cherry pick the latest version of a review from gerrit?

Is there a scriptable way to cherry pick the latest version of a gerrit patch review?

On Gerrit interface you can easile copy the code for a cherry pick but this code specifies a specific version and I am interested about some bash code that would pick the latest version instead of a specific one.

git fetch https://review.gerrithub.io/org-name/project-name refs/changes/02/12345/5 && git cherry-pick FETCH_HEAD

As you can see this will pick version 5.

Update

git review -s
git review -x 123456

I tried the review -x approach locally and it worked but running the some from Jenkins failed:

Could not connect to gerrit.
Enter your gerrit username: <traceback object at 0x285ecf8>
We don't know where your gerrit is. Please manually create a remote
named "gerrit" and try again.

Upvotes: 2

Views: 2540

Answers (2)

sorin
sorin

Reputation: 170598

Based on @larsks response I was able to write one version that really works for me. His original one failed on OS X due to old awk and also failed to pick the latest build by lacking numerical sorting (10 > 2 not between 1 and 2).

find_latest_change () {
  local remote=$1
  local review=$2
  git ls-remote $remote | grep -E "refs/changes/[[:digit:]]+/$2/" | sort -t / -k 5 -g | tail -n1 | awk '{print $2}'
}

remote=https://review.gerrithub.io/org-name/project-name
latest=$(find_latest_change $remote 12345)
git fetch $remote $latest && git cherry-pick FETCH_HEAD

Upvotes: 0

larsks
larsks

Reputation: 312018

The git-review tool makes this very easy. It uses the gerrit API to find the latest changeset available for a given review.

For example, you can just run...

git review -x 12345

...to cherry-pick the latest version of the named change into your local branch. There is also a -d option which will expose the change as a new branch, which is useful for reviewing things locally.

It's also a useful tool for submitting changes.

If you didn't want to use git-review, you could obviously make use of the Gerrit API yourself to find the appropriate reference for the latest changeset. For exampel:

ssh -p <gerrit_port> <gerrit_user>@<gerrit_host> gerrit query --current-patch-set --format json <review_number>

This gives you a chunk of JSON describing the given change, including information about the current patch set. You could extract that by piping the JSON to something like:

jq -r .currentPatchSet.ref

A complete example, using the git-review project itself:

$ ssh -p 29418 [email protected] \
  gerrit  query --current-patch-set --format json 281504 \
  | head -1 | jq -r .currentPatchSet.ref
refs/changes/04/281504/8

Update

There's another way to do this using just git commands. You can use the git ls-remote command to a list of remote references, which might looking something like:

$ git ls-remote https://review.gerrithub.io/org-name/project-name
211fd8c368d27a0c64ad260b8556ab11211b071a        refs/changes/00/328300/1
f9a4f3206fa9746acc3aac044cd4ae8b31763186        refs/changes/00/328300/2
3c89f1432aed33514e57bf40764605675fc0e782        refs/changes/00/328300/3
cdf0b56f07009e0d87b605b98257fdb6352ff235        refs/changes/00/328300/4
6b8ef89aed4470be7a230412f0c73f7cce429eda        refs/changes/00/328300/5
640f49347b19bec17360b613014e7af67054e2c8        refs/changes/00/328300/6
a45f2e9b05459faecdda8979aef4a87983e2f8a3        refs/changes/00/331800/1
7fab4ee270c21cd110388c01670a7ff4d1cbf41b        refs/changes/00/334600/1
5944ffe73bc1cdaea26b0151b4c1e93ac1235584        refs/changes/00/334600/2
fc3789ac553484ce81c47dc0adb09128dfb43077        refs/changes/00/334600/3
8aa3592d48c686dd6313a4b8087addfd5a108491        refs/changes/00/334600/4
520b5c135d2889af90689d049aacf6138cca8c61        refs/changes/00/334600/5

If we wanted the reference for the most recent patches for review 328300, we could extract that from the above like this:

git ls-remote https://review.gerrithub.io/org-name/project-name |
  awk '{print $2}' |
  awk -F/ '$4 == "328300" {print $0, $5}' |
  sort -k4 -n | tail -1 | awk '{print $1}'

Which gives us:

refs/changes/00/328300/6

So, rolling that up into a function and using that to cherry pick a review:

find_latest_change () {
  local remote=$1
  local review=$2

  git ls-remote $remote |
    awk '{print $2}' |
    awk -F/ -vreview=$review '$4 == review {print $0, $5}' |
    sort -k4 -n |
    tail -1 | 
    awk '{print $1}'
}

remote=https://review.gerrithub.io/org-name/project-name
latest=$(find_latest_change $remote 12345)
git fetch $remote $latest && 
  git cherry-pick FETCH_HEAD

Upvotes: 2

Related Questions