Roughly speaking, this changes (assuming 3 upstream PRs) git merge <upstream-commit1> <upstream-commit-2> <upstream-commit3> into git merge <upstream-commit3> This is more intuitive. We're merging a single upstream revision, namely <upstream-commit3>. The other two commits are simply parents of that one, i.e., they're included anyway, and git merge ignores them. (In fact, passing multiple refs looks like we're doing an octopus merge. It's just that git recognizes the fact that everything is included in the last ref anyway, and behaves as if only the last one had been passed.) This commit also makes some further clean ups and improvements.
144 lines
4.3 KiB
Bash
Executable File
144 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -eou pipefail
|
|
|
|
help() {
|
|
echo "Sync merge commits from bitcoin-core/secp256k1 into secp256k1-zkp."
|
|
echo
|
|
echo "Usage:"
|
|
echo " $0 [-b <branch>] [end]"
|
|
echo " Merges every merge commit present in upstream/master and missing in <branch>"
|
|
echo " (default: master). If the optional [end] commit is provided, only merges"
|
|
echo " up to and including [end]."
|
|
echo
|
|
echo "This tool creates a temporary branch and attempts to merge the upstream commits."
|
|
echo "If there are merge conflicts, resolve them and run tests, then use the generated"
|
|
echo "script contrib/gh-pr-create.sh to create the PR (requires the gh tool)."
|
|
echo
|
|
echo "Setup:"
|
|
echo " Requires a remote named 'upstream' pointing to bitcoin-core/secp256k1."
|
|
echo " The script will fetch it automatically, and offer to create it if missing."
|
|
echo " To add manually: git remote add upstream git@github.com:bitcoin-core/secp256k1.git"
|
|
echo
|
|
echo "Listing upstream merge commits:"
|
|
echo " To list merge commits in upstream/master that are missing from <branch> (oldest first):"
|
|
echo " git log --oneline --topo-order --reverse --merges \$(git merge-base upstream/master <branch>)..upstream/master"
|
|
echo " These are candidates for [end]."
|
|
exit 1
|
|
}
|
|
|
|
REMOTE=upstream
|
|
REMOTE_BRANCH="$REMOTE/master"
|
|
LOCAL_BRANCH="master"
|
|
# Makes sure you have a remote "upstream" that is up-to-date
|
|
setup() {
|
|
ret=0
|
|
git fetch "$REMOTE" &> /dev/null || ret="$?"
|
|
if [ ${ret} == 0 ]; then
|
|
return
|
|
fi
|
|
echo "Adding remote \"$REMOTE\" with URL git@github.com:bitcoin-core/secp256k1.git. Continue with y"
|
|
read -r yn
|
|
case $yn in
|
|
[Yy]* ) ;;
|
|
* ) exit 1;;
|
|
esac
|
|
git remote add "$REMOTE" git@github.com:bitcoin-core/secp256k1.git &> /dev/null
|
|
git fetch "$REMOTE" &> /dev/null
|
|
}
|
|
|
|
range() {
|
|
RANGESTART_COMMIT=$(git merge-base "$REMOTE_BRANCH" "$LOCAL_BRANCH")
|
|
RANGEEND_COMMIT=$(git rev-parse "$REMOTE_BRANCH")
|
|
if [ "$#" = 1 ]; then
|
|
RANGEEND_COMMIT=$1
|
|
fi
|
|
COMMITS=$(git --no-pager log --pretty=format:%H --topo-order --reverse --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT")
|
|
}
|
|
|
|
# Process -b <branch> and -h arguments
|
|
while getopts "b:h" opt; do
|
|
case $opt in
|
|
b)
|
|
LOCAL_BRANCH=$OPTARG
|
|
;;
|
|
h)
|
|
help
|
|
;;
|
|
*)
|
|
echo
|
|
help
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Shift off the processed options
|
|
shift $((OPTIND -1))
|
|
|
|
setup
|
|
range "$@"
|
|
|
|
TITLE="Upstream PRs"
|
|
REPRODUCE_COMMAND="$0 -b $LOCAL_BRANCH $RANGEEND_COMMIT"
|
|
BODY=""
|
|
for COMMIT in $COMMITS
|
|
do
|
|
PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\).*'/'\2'/)
|
|
TITLE="$TITLE $PRNUM,"
|
|
BODY=$(printf "%s\n%s" "$BODY" "$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\)'/'[bitcoin-core\/secp256k1#\2]'/)")
|
|
LAST_COMMIT="$COMMIT"
|
|
done
|
|
# Remove trailing ","
|
|
TITLE=${TITLE%?}
|
|
BODY+=$(cat <<EOF
|
|
|
|
|
|
This PR can be recreated with \`$REPRODUCE_COMMAND\`.
|
|
|
|
Tips:
|
|
* Use \`git show --remerge-diff <pr-branch>\` to show the conflict resolution in the merge commit.
|
|
* Use \`git read-tree --reset -u <pr-branch>\` to replay these resolutions during the conflict resolution stage when recreating the PR branch locally.
|
|
Be aware that this may discard your index as well as the uncommitted changes and untracked files in your worktree.
|
|
EOF
|
|
)
|
|
|
|
echo "Merging $TITLE. Continue with y"
|
|
read -r yn
|
|
case $yn in
|
|
[Yy]* ) ;;
|
|
* ) exit 1;;
|
|
esac
|
|
|
|
echo "-----------------------------------"
|
|
echo "$TITLE"
|
|
echo "-----------------------------------"
|
|
echo "$BODY"
|
|
echo "-----------------------------------"
|
|
# Create branch from PR commit and create PR
|
|
git checkout "$LOCAL_BRANCH"
|
|
git pull --autostash
|
|
git checkout -b temp-merge-"$PRNUM"
|
|
|
|
# Escape single quote
|
|
# ' -> '\''
|
|
quote() {
|
|
local quoted=${1//\'/\'\\\'\'}
|
|
printf "%s" "$quoted"
|
|
}
|
|
TITLE=$(quote "$TITLE")
|
|
BODY=$(quote "$BODY")
|
|
|
|
BASEDIR=$(dirname "$0")
|
|
FNAME="$BASEDIR/gh-pr-create.sh"
|
|
cat <<EOT > "$FNAME"
|
|
#!/bin/sh
|
|
gh pr create -t '$TITLE' -b '$BODY' --web
|
|
# Remove temporary branch
|
|
git checkout "$LOCAL_BRANCH"
|
|
git branch -D temp-merge-"$PRNUM"
|
|
EOT
|
|
chmod +x "$FNAME"
|
|
echo Run "$FNAME" after solving the merge conflicts
|
|
|
|
git merge --no-edit -m "Merge upstream '${LAST_COMMIT:0:7}' into temp-merge-$PRNUM" "$LAST_COMMIT"
|