From ca6828e993417b7b68d3540d70dd97d2f482564e Mon Sep 17 00:00:00 2001 From: Chris Stone Date: Wed, 5 Jul 2023 23:18:51 -0600 Subject: [PATCH] feat: add cherrypick option to hotfix finish (#73) Allows for the commits that resolve the hotfix to be applied to the develop branch instead of the entire hotfix branch. This option is not compatible with the nobackmerge or releaseBackmerge flags. The initial pull request provided by [simonweil](https://github.com/simonweil) closes #67 closes #37 closes petervanderdoes#164 closes petervanderdoes#165 Co-authored-by: simonweil --- git-flow-hotfix | 59 +++++++++++++++++++++++++++++++++++++++++++++---- gitflow-common | 19 ++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/git-flow-hotfix b/git-flow-hotfix index b037d68b..17c88cf1 100644 --- a/git-flow-hotfix +++ b/git-flow-hotfix @@ -366,7 +366,7 @@ showcommands! Show git commands while executing them cmd_finish() { OPTIONS_SPEC="\ -git flow hotfix finish [-h] [-F] [-s] [-u] [-m | -f ] [-p] [-k] [-n] [-b] [-S] +git flow hotfix finish [-h] [-F] [-s] [-u] [-m | -f ] [-p] [-k] [-n] [-b | -c] [-S] Finish hotfix branch -- @@ -387,6 +387,7 @@ b,[no]nobackmerge Don't back-merge master, or tag if applicable, in develop r,releaseBackmerge Back-merge to release branch if exists S,[no]squash Squash hotfix during merge T,tagname! Use given tag name +c,cherrypick Cherry Pick to $DEVELOP_BRANCH instead of merge " local opts commit keepmsg remotebranchdeleted localbranchdeleted @@ -407,6 +408,7 @@ T,tagname! Use given tag name DEFINE_boolean 'squash' false "squash release during merge" S DEFINE_boolean 'squash-info' false "add branch info during squash" DEFINE_string 'tagname' "" "use the given tag name" T + DEFINE_boolean 'cherrypick' false "Cherry Pick to $DEVELOP_BRANCH instead of merge" c # Override defaults with values from config gitflow_override_flag_boolean "hotfix.finish.fetch" "fetch" @@ -424,6 +426,7 @@ T,tagname! Use given tag name gitflow_override_flag_string "hotfix.finish.signingkey" "signingkey" gitflow_override_flag_string "hotfix.finish.message" "message" gitflow_override_flag_string "hotfix.finish.messagefile" "messagefile" + gitflow_override_flag_boolean "hotfix.finish.cherrypick" "cherrypick" # Parse arguments parse_args "$@" @@ -453,6 +456,15 @@ T,tagname! Use given tag name FLAGS_keep=$FLAGS_TRUE fi + # Check that not both no merge flags were given + if flag cherrypick && flag nobackmerge; then + die "You can't use 'cherrypick' and 'nobackmerge' together." + fi + + if flag cherrypick && flag releasebackmerge; then + die "You can't use 'cherrypick' and 'releasebackmerge' together." + fi + # Sanity checks require_branch "$BRANCH" require_clean_working_tree @@ -521,6 +533,42 @@ T,tagname! Use given tag name run_pre_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH" +if flag cherrypick; then +printf 'this is the cherrypick\n' +read + git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'." + + local old_IFS=$IFS # save the field separator + IFS=$'\n' # new field separator, the end of line + for git_line in $(git log --format="%H %s" --reverse $MASTER_BRANCH..$BRANCH | grep -vE "^[a-z0-9]* Merge branch '[^'].*?'$"); do + local commit_hash=$(echo $git_line | cut -d" " -f1) + if [[ $(git log $DEVELOP_BRANCH --grep "$commit_hash" | wc -l) -eq 0 ]]; then + echo "\n${LIGHTGREEN}Cherry picking: $git_line${NOCOLOR}" + git_do cherry-pick -x -s $commit_hash + if [[ $? -ne 0 ]]; then + echo " +=============================================================== += Cherry pick has conflicts, steps to continue: += 1. Fix the conflicts += 2. Stage the fixed file: '${BLUE}git add ${NOCOLOR}' += 3. Continue the cherry pick: '${BLUE}git cherry-pick --continue${NOCOLOR}' += *** If fixing the conflict results in an empty commit, += you will need to run this command: '${BLUE}git commit --allow-empty${NOCOLOR}' += 4. Switch back to the hotfix branch: '${BLUE}git checkout $BRANCH${NOCOLOR}' += 5. Rerun the finish command: '${BLUE}git flow hotfix finish${NOCOLOR}' += OR run '${BLUE}git cherry-pick --abort${NOCOLOR}' to abort the cherry pick +===============================================================\n" + die "Cherry pick failed for commit: $commit_hash" + fi + else + echo "\n${LIGHTGREEN}Commit has already been Cherry Picked: $git_line${NOCOLOR}" + fi + done + IFS=$old_IFS # restore default field separator + + git_do checkout $BRANCH || die "Could not check out branch '$BRANCH'." + fi + # Try to merge into BASE. # In case a previous attempt to finish this release branch has failed, # but the merge into BASE was successful, we skip it now @@ -556,7 +604,7 @@ T,tagname! Use given tag name fi fi - if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ] && noflag nobackmerge; then + if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ] && noflag nobackmerge && noflag cherrypick; then # Try to merge into develop unless the user specified the nobackmerge option. # In case a previous attempt to finish this release branch has failed, # but the merge into develop was successful, we skip it now @@ -660,12 +708,15 @@ T,tagname! Use given tag name if noflag notag; then echo "- The hotfix was tagged '$VERSION_PREFIX$TAGNAME'" fi - if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then + if flag cherrypick; then + echo "- All commits from the hotfix branch have been cherry picked into '$DEVELOP_BRANCH'" + elif [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then [ "$commit" = "$BASE_BRANCH" ] && echo "- Master branch '$BASE_BRANCH' has been back-merged into '$DEVELOP_BRANCH'" [ -n "$release_branch" ] && echo "- Hotfix tag '$VERSION_PREFIX$TAGNAME' has been back-merged into '$release_branch'" - [ "$commit" = "$VERSION_PREFIX$TAGNAME" ] && echo "- Hotfix tag '$VERSION_PREFIX$TAGNAME' has been back-merged into '$DEVELOP_BRANCH'" + [ "$commit" = "$VERSION_PREFIX$VERSION" ] && echo "- Hotfix tag '$VERSION_PREFIX$VERSION' has been back-merged into '$DEVELOP_BRANCH'" [ "$commit" = "$BRANCH" ] && echo "- Hotfix branch '$BRANCH' has been merged into '$DEVELOP_BRANCH'" fi + if noflag keep; then if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then keepmsg="has been locally deleted" diff --git a/gitflow-common b/gitflow-common index 175637ba..dcd78e35 100644 --- a/gitflow-common +++ b/gitflow-common @@ -811,3 +811,22 @@ run_post_hook() { flags_help() { eval "$( echo "$OPTIONS_SPEC" | git rev-parse --parseopt -- "-h" || echo exit $? )" } + +# +# Color constants +# +echo_color_support() { + local echo_path=$(which echo) + local echo_out=$($echo_path -e) + if [[ $echo_out == "" ]]; then + alias echo="$echo_path -e " + BLUE="\e[34m" + LIGHTGREEN="\e[92m" + NOCOLOR="\e[0m" + else + BLUE="" + LIGHTGREEN="" + NOCOLOR="" + fi +} +echo_color_support \ No newline at end of file