diff options
author | Patrick Georgi <pgeorgi@chromium.org> | 2016-09-22 12:46:45 +0200 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2016-10-10 20:18:57 +0200 |
commit | 519c4b7298516c849b4a510ad2fd691d662de7d6 (patch) | |
tree | 08eaae4cfa81c8f6539391cae131ab0039f8cb2f /util | |
parent | 0de17e74ff428cefc95d8788e58ad11ec5f70085 (diff) |
util/scripts: add gerrit-rebase script
gerrit-rebase is a gerrit-context aware rebase script. Given a source
and a target branch (that need to have a common ancestor), it prepares
a rebase todo list that applies all commits from source that aren't
already found on target.
It matches commits using Reviewed-on lines in the commit message that
are added by gerrit when submitting commits using the "cherry-pick"
strategy.
This has been shown to be the best preserved meta data to work from in
existing data (Change-Id was mangled in all kinds of ways).
Change-Id: I9618c1b66ebc1fb7ed006efbc1665fb08386e1a5
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Reviewed-on: https://review.coreboot.org/16695
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'util')
-rwxr-xr-x | util/scripts/gerrit-rebase | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/util/scripts/gerrit-rebase b/util/scripts/gerrit-rebase new file mode 100755 index 0000000000..002c499f8c --- /dev/null +++ b/util/scripts/gerrit-rebase @@ -0,0 +1,61 @@ +#!/bin/bash +# $0 from-branch to-branch +# applies all commits that from-branch has over to-branch, +# based on a common ancestor and gerrit meta-data +from=$1 +to=$2 + +# match string: this is the git commit line that is used to +# identify commits that were already copied over. +# +# Must not contain spaces except for leading and trailing. +# +# The first pick was Change-Id, but it was lost too often, +# so go for Reviewed-on instead. It's also unique because it +# contains the gerrit instance's host name and the change's number +# on that system. +match_string='^ [-A-Za-z]*[Rr]eviewed-on: ' + +# fetch common ancestor +common_base=$(git merge-base ${from} ${to} 2>/dev/null) + +if [ -z "${common_base}" ]; then + echo \"${from}\" or \"${to}\" is not a valid branch name. + exit 1 +fi + +# collect matches that are present on the target side +to_matches="$(git log ${common_base}..${to} | \ + grep "${match_string}" | \ + cut -d: -f2-)" + +# start rebase process, but fail immediately by enforcing an invalid todo +GIT_SEQUENCE_EDITOR="echo foo >" \ + git rebase -i --onto ${to} ${from} ${to} 2>/dev/null + +# write new rebase todo +# the appended "commit" line triggers handling of the last log entry +commit="" +(git log --reverse ${common_base}..${from} | \ + grep -E "(^commit [0-9a-f]{40}\$|${match_string})"; \ + echo "commit") | \ +while read key value; do + if [ "${key}" = "commit" ]; then + if [ -n "${commit}" ]; then + git log -n 1 --pretty="pick %h %s" ${commit} + fi + commit="${value}" + else + # if value was already found on the "to" side, skip this + # commit + if [[ ${to_matches} == *"${value}"* ]]; then + commit="" + fi + fi +done | GIT_SEQUENCE_EDITOR="cat >" git rebase --edit-todo + +# allow user to edit todo +git rebase --edit-todo + +# start processing todo to mimick git rebase -i behavior +git rebase --continue |