diff --git a/docs/releasing.md b/docs/releasing.md index 6efe53eaaaa1..2e8b4226baca 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -9,10 +9,10 @@ to work well with our versioned website. Then get a list of commits you may want to cherry-pick: ```bash -./hack/cherry-pick.sh release-3.3 "fix" true -./hack/cherry-pick.sh release-3.3 "chore(deps)" true -./hack/cherry-pick.sh release-3.3 "build" true -./hack/cherry-pick.sh release-3.3 "ci" true +./hack/cherry-pick.sh release-3.3 "fix" +./hack/cherry-pick.sh release-3.3 "chore(deps)" +./hack/cherry-pick.sh release-3.3 "build" +./hack/cherry-pick.sh release-3.3 "ci" ``` To automatically cherry-pick, run the following: diff --git a/hack/cherry-pick.sh b/hack/cherry-pick.sh index 4e8e5d2ded89..16ffddc81a0f 100755 --- a/hack/cherry-pick.sh +++ b/hack/cherry-pick.sh @@ -1,46 +1,56 @@ #!/usr/bin/env bash set -eu -# See docs/releasing.md for instructions. +# See ../docs/releasing.md for instructions. -br="$1" # branch name, e.g. release-3.3 +branch="$1" # branch name, e.g. release-3.3 commitPrefix="$2" # prefix to use to filter commits, e.g. fix, chore(deps), build, ci -# whether this is dry-run. If set to `true`, this script will only print out the list -# of commits. Otherwise, this script will automatically cherry-pick the commits to the branch. -dryRun="$3" +# If dryRun is unset or `true`, only print the list of commits to be cherry-picked. +# Otherwise, cherry-pick the commits to the specified branch. +dryRun="${3:-"true"}" + +# unfortunately, cherry-picking to another branch is not possible, so error out if not on the branch (c.f. https://stackoverflow.com/q/13878904/3431180) +curr_branch=$(git rev-parse --abbrev-ref HEAD) +if [[ "$curr_branch" != "$branch" ]]; then + echo "Current branch is '$curr_branch', but trying to cherry-pick to branch '$branch'. You must have branch '$branch' checked out in order to cherry-pick" + exit 1 +fi commitGrepPattern="^${commitPrefix}(*.*)*:.*(#" # find the branch point -base=$(git merge-base "$br" main) +base=$(git merge-base "$branch" main) # extract the PRs from stdin -prNo() { - set -eu +getPRNum() { cat | sed "s|.*(\(#[0-9]*\))|\1|" } # list the PRs on each branch -prs() { - set -eu - git log --format="%s" --grep "${commitGrepPattern}" "$1...$2" | prNo | sort > "/tmp/$2" +getPRs() { + git log --format="%s" --grep "${commitGrepPattern}" "$1...$2" | getPRNum | sort > "/tmp/$2" } -prs "$base" "$br" -prs "$base" main +getPRs "$base" "$branch" +getPRs "$base" main # find PRs added to main -diff "/tmp/$br" /tmp/main | grep "^> " | cut -c 3- > /tmp/prs +diff "/tmp/$branch" /tmp/main | grep "^> " | cut -c 3- > /tmp/prs # print all the commits that need cherry-picking -git log --oneline --grep "${commitGrepPattern}" "$base...main" | while read -r m; do +git log --oneline --grep "${commitGrepPattern}" "$base...main" | tac | while read -r m; do + if ! grep -q "$(echo "$m" | getPRNum)" /tmp/prs ; then + continue + fi + if [[ "$dryRun" == "true" ]]; then - grep -q "$(echo "$m" | prNo)" /tmp/prs && echo "$m" - else - commit=$(grep -q "$(echo "$m" | prNo)" /tmp/prs && echo "${m:0:9}") - echo "cherry-picking: $commit" - if ! git cherry-pick "$commit"; then - echo "failed to cherry-pick $commit" - git cherry-pick --abort - fi + echo "$m" + continue + fi + + commit=${m:0:9} + echo "cherry-picking: $commit" + if ! git cherry-pick "$commit" -x -Xpatience ; then + echo "failed to cherry-pick $commit" + git cherry-pick --abort fi done