8f8668d87f
This might provide a minor speedup but more importantly it allows skipping commits without Reviewed-on line (which we have a couple of due to mistakes with git push). To use, add a line starting with "Gerrit-Rebase-Ignore-CLs-Before:" pointing out a match string (ie "something that comes after Reviewed-on") prior to which no changes are considered on the originating branch. The target branch is still fully considered to avoid issues with changes that were retargetted out of order around the new cut and would then make a reappearance (or be skipped). Change-Id: I9f2679891e93f6d28a781315aebd2aa60a1e3b23 Signed-off-by: Patrick Georgi <pgeorgi@google.com> Reviewed-on: https://review.coreboot.org/20185 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com>
102 lines
3.2 KiB
Bash
Executable file
102 lines
3.2 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Copyright 2016 Google Inc.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; version 2 of the License.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
|
|
# $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:'
|
|
|
|
# Custom root: allow a certain CL (identified by matching either side's
|
|
# match_string) to be the new root, instead of using git's common history only.
|
|
# This allows cutting down on commits that are re-evaluated on every run.
|
|
#
|
|
# Use:
|
|
# To the commit message of a commit on the "to" side, add
|
|
# $custom_root: match_string (the part coming after $match_string)
|
|
#
|
|
# For a $match_string of ~ "Reviewed-on: " this might
|
|
# be "$custom_root: https://example.com/12345"
|
|
#
|
|
# On traversal, the commit with "$match_string: https://example.com/12345"
|
|
# is then considered a base commit.
|
|
custom_root='^Gerrit-Rebase-Ignore-CLs-Before:'
|
|
|
|
# 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
|
|
|
|
from_base=$common_base
|
|
|
|
# fetch custom root ID
|
|
croot_marker=$(git log --pretty=%b -1 --grep "${custom_root}" \
|
|
${common_base}..${to} | \
|
|
grep "${custom_root}" | cut -d: -f2-)
|
|
if [ -n "${croot_marker}" ]; then
|
|
from_base=$( ( \
|
|
git log --pretty=%H -1 \
|
|
--grep "^${match_string}${croot_marker}" \
|
|
${from_base}..${from}; echo ${from_base} )| head -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 ${from_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
|