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