Patrick Georgi | 519c4b7 | 2016-09-22 12:46:45 +0200 | [diff] [blame] | 1 | #!/bin/bash |
Patrick Georgi | 4003283 | 2016-10-24 11:58:07 +0200 | [diff] [blame^] | 2 | |
| 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 Georgi | 519c4b7 | 2016-09-22 12:46:45 +0200 | [diff] [blame] | 14 | # $0 from-branch to-branch |
Patrick Georgi | 4003283 | 2016-10-24 11:58:07 +0200 | [diff] [blame^] | 15 | # |
Patrick Georgi | 519c4b7 | 2016-09-22 12:46:45 +0200 | [diff] [blame] | 16 | # applies all commits that from-branch has over to-branch, |
| 17 | # based on a common ancestor and gerrit meta-data |
| 18 | from=$1 |
| 19 | to=$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. |
| 30 | match_string='^ [-A-Za-z]*[Rr]eviewed-on: ' |
| 31 | |
| 32 | # fetch common ancestor |
| 33 | common_base=$(git merge-base ${from} ${to} 2>/dev/null) |
| 34 | |
| 35 | if [ -z "${common_base}" ]; then |
| 36 | echo \"${from}\" or \"${to}\" is not a valid branch name. |
| 37 | exit 1 |
| 38 | fi |
| 39 | |
| 40 | # collect matches that are present on the target side |
| 41 | to_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 |
| 46 | GIT_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 |
| 51 | commit="" |
| 52 | (git log --reverse ${common_base}..${from} | \ |
| 53 | grep -E "(^commit [0-9a-f]{40}\$|${match_string})"; \ |
| 54 | echo "commit") | \ |
| 55 | while 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 |
| 68 | done | GIT_SEQUENCE_EDITOR="cat >" git rebase --edit-todo |
| 69 | |
| 70 | # allow user to edit todo |
| 71 | git rebase --edit-todo |
| 72 | |
| 73 | # start processing todo to mimick git rebase -i behavior |
| 74 | git rebase --continue |