Patrick Georgi | 519c4b7 | 2016-09-22 12:46:45 +0200 | [diff] [blame^] | 1 | #!/bin/bash |
| 2 | # $0 from-branch to-branch |
| 3 | # applies all commits that from-branch has over to-branch, |
| 4 | # based on a common ancestor and gerrit meta-data |
| 5 | from=$1 |
| 6 | to=$2 |
| 7 | |
| 8 | # match string: this is the git commit line that is used to |
| 9 | # identify commits that were already copied over. |
| 10 | # |
| 11 | # Must not contain spaces except for leading and trailing. |
| 12 | # |
| 13 | # The first pick was Change-Id, but it was lost too often, |
| 14 | # so go for Reviewed-on instead. It's also unique because it |
| 15 | # contains the gerrit instance's host name and the change's number |
| 16 | # on that system. |
| 17 | match_string='^ [-A-Za-z]*[Rr]eviewed-on: ' |
| 18 | |
| 19 | # fetch common ancestor |
| 20 | common_base=$(git merge-base ${from} ${to} 2>/dev/null) |
| 21 | |
| 22 | if [ -z "${common_base}" ]; then |
| 23 | echo \"${from}\" or \"${to}\" is not a valid branch name. |
| 24 | exit 1 |
| 25 | fi |
| 26 | |
| 27 | # collect matches that are present on the target side |
| 28 | to_matches="$(git log ${common_base}..${to} | \ |
| 29 | grep "${match_string}" | \ |
| 30 | cut -d: -f2-)" |
| 31 | |
| 32 | # start rebase process, but fail immediately by enforcing an invalid todo |
| 33 | GIT_SEQUENCE_EDITOR="echo foo >" \ |
| 34 | git rebase -i --onto ${to} ${from} ${to} 2>/dev/null |
| 35 | |
| 36 | # write new rebase todo |
| 37 | # the appended "commit" line triggers handling of the last log entry |
| 38 | commit="" |
| 39 | (git log --reverse ${common_base}..${from} | \ |
| 40 | grep -E "(^commit [0-9a-f]{40}\$|${match_string})"; \ |
| 41 | echo "commit") | \ |
| 42 | while read key value; do |
| 43 | if [ "${key}" = "commit" ]; then |
| 44 | if [ -n "${commit}" ]; then |
| 45 | git log -n 1 --pretty="pick %h %s" ${commit} |
| 46 | fi |
| 47 | commit="${value}" |
| 48 | else |
| 49 | # if value was already found on the "to" side, skip this |
| 50 | # commit |
| 51 | if [[ ${to_matches} == *"${value}"* ]]; then |
| 52 | commit="" |
| 53 | fi |
| 54 | fi |
| 55 | done | GIT_SEQUENCE_EDITOR="cat >" git rebase --edit-todo |
| 56 | |
| 57 | # allow user to edit todo |
| 58 | git rebase --edit-todo |
| 59 | |
| 60 | # start processing todo to mimick git rebase -i behavior |
| 61 | git rebase --continue |