blob: 8f59e7f497035d0d070becf46d38f328f373489d [file] [log] [blame]
Patrick Georgi519c4b72016-09-22 12:46:45 +02001#!/bin/bash
Patrick Georgi40032832016-10-24 11:58:07 +02002
3# Copyright 2016 Google Inc.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; version 2 of the License.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13
Patrick Georgi519c4b72016-09-22 12:46:45 +020014# $0 from-branch to-branch
Patrick Georgi40032832016-10-24 11:58:07 +020015#
Patrick Georgi519c4b72016-09-22 12:46:45 +020016# applies all commits that from-branch has over to-branch,
17# based on a common ancestor and gerrit meta-data
18from=$1
19to=$2
20
21# match string: this is the git commit line that is used to
22# identify commits that were already copied over.
23#
24# Must not contain spaces except for leading and trailing.
25#
26# The first pick was Change-Id, but it was lost too often,
27# so go for Reviewed-on instead. It's also unique because it
28# contains the gerrit instance's host name and the change's number
29# on that system.
30match_string='^ [-A-Za-z]*[Rr]eviewed-on: '
31
32# fetch common ancestor
33common_base=$(git merge-base ${from} ${to} 2>/dev/null)
34
35if [ -z "${common_base}" ]; then
36 echo \"${from}\" or \"${to}\" is not a valid branch name.
37 exit 1
38fi
39
40# collect matches that are present on the target side
41to_matches="$(git log ${common_base}..${to} | \
42 grep "${match_string}" | \
43 cut -d: -f2-)"
44
45# start rebase process, but fail immediately by enforcing an invalid todo
46GIT_SEQUENCE_EDITOR="echo foo >" \
47 git rebase -i --onto ${to} ${from} ${to} 2>/dev/null
48
49# write new rebase todo
50# the appended "commit" line triggers handling of the last log entry
51commit=""
52(git log --reverse ${common_base}..${from} | \
53 grep -E "(^commit [0-9a-f]{40}\$|${match_string})"; \
54 echo "commit") | \
55while read key value; do
56 if [ "${key}" = "commit" ]; then
57 if [ -n "${commit}" ]; then
58 git log -n 1 --pretty="pick %h %s" ${commit}
59 fi
60 commit="${value}"
61 else
62 # if value was already found on the "to" side, skip this
63 # commit
64 if [[ ${to_matches} == *"${value}"* ]]; then
65 commit=""
66 fi
67 fi
68done | GIT_SEQUENCE_EDITOR="cat >" git rebase --edit-todo
69
70# allow user to edit todo
71git rebase --edit-todo
72
73# start processing todo to mimick git rebase -i behavior
74git rebase --continue