88# http://blog.avirtualhome.com/development-workflow-using-git/
99#
1010# Feel free to contribute to this project at:
11- # http://github.com/petervanderdoes /gitflow
11+ # http://github.com/CJ-Systems /gitflow-cjs
1212#
1313# Authors:
14+ # Copyright 2003 CJ Systems. All rights reserved.
1415# Copyright 2012-2019 Peter van der Does. All rights reserved.
1516#
1617# Original Author:
@@ -348,23 +349,24 @@ showcommands! Show git commands while executing them
348349
349350 # Sanity checks
350351 require_clean_working_tree
351- require_branch_absent " $BRANCH "
352- git_do fetch -q " $ORIGIN "
353- require_branch " $ORIGIN /$BRANCH "
352+ require_local_branch_absent " $BRANCH "
353+
354+ git_do fetch -q " $ORIGIN " || die " Could not fetch branch '$BRANCH ' from remote '$ORIGIN '."
355+ git_remote_branch_exists " $ORIGIN /$BRANCH "
354356
355357 # Create tracking branch
356- git_do checkout -b " $BRANCH " " $ORIGIN /$BRANCH "
358+ git_do checkout -b " $BRANCH " " $ORIGIN /$BRANCH " || die " Could not create branch ' $BRANCH '. "
357359
358360 echo
359361 echo " Summary of actions:"
360362 echo " - A new remote tracking branch '$BRANCH ' was created"
361- echo " - You are now on branch '$BRANCH '"
363+ echo " - You are now on branch '$( git_current_branch ) '"
362364 echo
363365}
364366
365367cmd_finish () {
366368 OPTIONS_SPEC=" \
367- git flow hotfix finish [-h] [-F] [-s] [-u] [-m | -f ] [-p] [-k] [-n] [-b] [-S] <version>
369+ git flow hotfix finish [-h] [-F] [-s] [-u] [-m | -f ] [-p] [-k] [-n] [-b | -c | -r ] [-S] <version>
368370
369371Finish hotfix branch <version>
370372--
@@ -382,8 +384,10 @@ k,[no]keep Keep branch after performing finish
382384D,[no]force_delete Force delete hotfix branch after finish
383385n,[no]notag Don't tag this hotfix
384386b,[no]nobackmerge Don't back-merge master, or tag if applicable, in develop
387+ r,releaseBackmerge Back-merge to release branch if exists
385388S,[no]squash Squash hotfix during merge
386389T,tagname! Use given tag name
390+ c,cherrypick Cherry Pick to $DEVELOP_BRANCH instead of merge
387391"
388392 local opts commit keepmsg remotebranchdeleted localbranchdeleted
389393
@@ -400,25 +404,29 @@ T,tagname! Use given tag name
400404 DEFINE_boolean ' force_delete' false " force delete hotfix branch after finish" D
401405 DEFINE_boolean ' notag' false " don't tag this hotfix" n
402406 DEFINE_boolean ' nobackmerge' false " don't back-merge $MASTER_BRANCH , or tag if applicable, in $DEVELOP_BRANCH " b
407+ DEFINE_boolean ' releasebackmerge' false " back-merge to release branch if exists" r
403408 DEFINE_boolean ' squash' false " squash release during merge" S
404409 DEFINE_boolean ' squash-info' false " add branch info during squash"
405410 DEFINE_string ' tagname' " " " use the given tag name" T
411+ DEFINE_boolean ' cherrypick' false " Cherry Pick to $DEVELOP_BRANCH instead of merge" c
406412
407413 # Override defaults with values from config
408- gitflow_override_flag_boolean " hotfix.finish.fetch" " fetch"
409- gitflow_override_flag_boolean " hotfix.finish.sign" " sign"
410- gitflow_override_flag_boolean " hotfix.finish.push" " push"
411- gitflow_override_flag_boolean " hotfix.finish.keep" " keep"
412- gitflow_override_flag_boolean " hotfix.finish.keepremote" " keepremote"
413- gitflow_override_flag_boolean " hotfix.finish.keeplocal" " keeplocal"
414- gitflow_override_flag_boolean " hotfix.finish.force-delete" " force_delete"
415- gitflow_override_flag_boolean " hotfix.finish.notag" " notag"
416- gitflow_override_flag_boolean " hotfix.finish.nobackmerge" " nobackmerge"
417- gitflow_override_flag_boolean " hotfix.finish.squash" " squash"
418- gitflow_override_flag_boolean " hotfix.finish.squash-info" " squash_info"
419- gitflow_override_flag_string " hotfix.finish.signingkey" " signingkey"
420- gitflow_override_flag_string " hotfix.finish.message" " message"
421- gitflow_override_flag_string " hotfix.finish.messagefile" " messagefile"
414+ gitflow_override_flag_boolean " hotfix.finish.fetch" " fetch"
415+ gitflow_override_flag_boolean " hotfix.finish.sign" " sign"
416+ gitflow_override_flag_boolean " hotfix.finish.push" " push"
417+ gitflow_override_flag_boolean " hotfix.finish.keep" " keep"
418+ gitflow_override_flag_boolean " hotfix.finish.keepremote" " keepremote"
419+ gitflow_override_flag_boolean " hotfix.finish.keeplocal" " keeplocal"
420+ gitflow_override_flag_boolean " hotfix.finish.force-delete" " force_delete"
421+ gitflow_override_flag_boolean " hotfix.finish.notag" " notag"
422+ gitflow_override_flag_boolean " hotfix.finish.nobackmerge" " nobackmerge"
423+ gitflow_override_flag_boolean " hotfix.finish.releasebackmerge" " releasebackmerge"
424+ gitflow_override_flag_boolean " hotfix.finish.squash" " squash"
425+ gitflow_override_flag_boolean " hotfix.finish.squash-info" " squash_info"
426+ gitflow_override_flag_string " hotfix.finish.signingkey" " signingkey"
427+ gitflow_override_flag_string " hotfix.finish.message" " message"
428+ gitflow_override_flag_string " hotfix.finish.messagefile" " messagefile"
429+ gitflow_override_flag_boolean " hotfix.finish.cherrypick" " cherrypick"
422430
423431 # Parse arguments
424432 parse_args " $@ "
@@ -448,6 +456,19 @@ T,tagname! Use given tag name
448456 FLAGS_keep=$FLAGS_TRUE
449457 fi
450458
459+ # Check that not both no merge flags were given
460+ if flag cherrypick && flag nobackmerge; then
461+ die " You can't use 'cherrypick' and 'nobackmerge' together."
462+ fi
463+
464+ if flag cherrypick && flag releasebackmerge; then
465+ die " You can't use 'cherrypick' and 'releasebackmerge' together."
466+ fi
467+
468+ if flag nobackmerge && flag releasebackmerge; then
469+ die " You can't use 'nobackmerge' && 'releasebackmerge' together."
470+ fi
471+
451472 # Sanity checks
452473 require_branch " $BRANCH "
453474 require_clean_working_tree
@@ -516,6 +537,42 @@ T,tagname! Use given tag name
516537
517538 run_pre_hook " $VERSION_PREFIX$TAGNAME " " $ORIGIN " " $BRANCH "
518539
540+ if flag cherrypick; then
541+ printf ' this is the cherrypick\n'
542+ read
543+ git_do checkout " $DEVELOP_BRANCH " || die " Could not check out branch '$DEVELOP_BRANCH '."
544+
545+ local old_IFS=$IFS # save the field separator
546+ IFS=$' \n ' # new field separator, the end of line
547+ for git_line in $( git log --format=" %H %s" --reverse $MASTER_BRANCH ..$BRANCH | grep -vE " ^[a-z0-9]* Merge branch '[^'].*?'$" ) ; do
548+ local commit_hash=$( echo $git_line | cut -d" " -f1)
549+ if [[ $( git log $DEVELOP_BRANCH --grep " $commit_hash " | wc -l) -eq 0 ]]; then
550+ echo " \n${LIGHTGREEN} Cherry picking: $git_line ${NOCOLOR} "
551+ git_do cherry-pick -x -s $commit_hash
552+ if [[ $? -ne 0 ]]; then
553+ echo "
554+ ===============================================================
555+ = Cherry pick has conflicts, steps to continue:
556+ = 1. Fix the conflicts
557+ = 2. Stage the fixed file: '${BLUE} git add <file names>${NOCOLOR} '
558+ = 3. Continue the cherry pick: '${BLUE} git cherry-pick --continue${NOCOLOR} '
559+ = *** If fixing the conflict results in an empty commit,
560+ = you will need to run this command: '${BLUE} git commit --allow-empty${NOCOLOR} '
561+ = 4. Switch back to the hotfix branch: '${BLUE} git checkout $BRANCH ${NOCOLOR} '
562+ = 5. Rerun the finish command: '${BLUE} git flow hotfix finish${NOCOLOR} '
563+ = OR run '${BLUE} git cherry-pick --abort${NOCOLOR} ' to abort the cherry pick
564+ ===============================================================\n"
565+ die " Cherry pick failed for commit: $commit_hash "
566+ fi
567+ else
568+ echo " \n${LIGHTGREEN} Commit has already been Cherry Picked: $git_line ${NOCOLOR} "
569+ fi
570+ done
571+ IFS=$old_IFS # restore default field separator
572+
573+ git_do checkout $BRANCH || die " Could not check out branch '$BRANCH '."
574+ fi
575+
519576 # Try to merge into BASE.
520577 # In case a previous attempt to finish this release branch has failed,
521578 # but the merge into BASE was successful, we skip it now
@@ -551,44 +608,66 @@ T,tagname! Use given tag name
551608 fi
552609 fi
553610
554- if [ " $BASE_BRANCH " = " $MASTER_BRANCH " ]; then
555- # By default we back-merge the $MASTER_BRANCH unless the user explicitly
556- # stated not to do a back-merge, in that case we use the $BRANCH.
557- if noflag nobackmerge; then
558- MERGE_BRANCH=" $BASE_BRANCH "
559- else
560- MERGE_BRANCH=" $BRANCH "
561- fi
562-
563- # Try to merge into develop.
611+ if [ " $BASE_BRANCH " = " $MASTER_BRANCH " ] && noflag nobackmerge && noflag cherrypick; then
612+ # Try to merge into develop unless the user specified the nobackmerge option.
564613 # In case a previous attempt to finish this release branch has failed,
565614 # but the merge into develop was successful, we skip it now
566- if ! git_is_branch_merged_into " $MERGE_BRANCH " " $DEVELOP_BRANCH " ; then
615+ if ! git_is_branch_merged_into " $BASE_BRANCH " " $DEVELOP_BRANCH " ; then
616+ # Accounting for 'git describe', if a release is tagged
617+ # we use the tag commit instead of the branch.
618+ if noflag notag; then
619+ commit=" $VERSION_PREFIX$TAGNAME "
620+ else
621+ commit=" $BASE_BRANCH "
622+ fi
623+ # merge master to develop
567624 git_do checkout " $DEVELOP_BRANCH " || die " Could not check out branch '$DEVELOP_BRANCH '."
625+ git_do merge --no-ff " $commit " || die " There were merge conflicts." # TODO: What do we do now?
626+ fi
627+ fi
568628
569- if noflag nobackmerge; then
570- # Accounting for 'git describe', if a release is tagged
571- # we use the tag commit instead of the branch.
572- if noflag notag; then
573- commit=" $VERSION_PREFIX$TAGNAME "
574- else
575- commit=" $BASE_BRANCH "
576- fi
629+ if flag releasebackmerge; then
630+ _releasePrefix=$( git config --get gitflow.prefix.release)
631+ release_branches=$( git_local_branches_prefixed " $_releasePrefix " )
632+ release_branch=
633+ # Check if there is a release branch
634+ if [ -n " $release_branches " ]; then
635+ # Get the release branch name
636+ release_branch=$( echo ${release_branches} | head -n1)
637+ # Check if release branch exists on remote
638+ if git_remote_branch_exists " $ORIGIN /$release_branch " ; then
639+ # Try to merge into release.
640+ # In case a previous attempt to finish this release branch has failed,
641+ # but the merge into release was successful, we skip it now
642+ if ! git_is_branch_merged_into " $MERGE_BRANCH " " $release_branch " ; then
643+ git_do checkout " $release_branch " || die " Could not check out branch '$release_branch '."
644+ # Accounting for 'git describe', if a release is tagged
645+ # we use the tag commit instead of the branch.
646+ if noflag notag; then
647+ commit=" $VERSION_PREFIX$TAGNAME "
648+ else
649+ commit=" $BASE_BRANCH "
650+ fi
651+ else
652+ commit=" $BRANCH "
653+ fi
654+ git_do merge --no-ff " $commit " || die " There were merge conflicts."
655+ # TODO: What do we do now?
577656 else
578- commit= " $BRANCH "
657+ echo " Remote release $release_branch not found "
579658 fi
580-
581- git_do merge --no-ff " $commit " || die " There were merge conflicts."
582- # TODO: What do we do now?
583659 fi
584- fi
660+ fi
585661
586662 run_post_hook " $VERSION_PREFIX$TAGNAME " " $ORIGIN " " $BRANCH "
587663
588664 if flag push; then
589665 if [ " $BASE_BRANCH " = " $MASTER_BRANCH " ]; then
590666 git_do push " $ORIGIN " " $DEVELOP_BRANCH " || die " Could not push branch '$DEVELOP_BRANCH ' to remote '$ORIGIN '."
591667 fi
668+ if [ -n " $release_branch " ]; then
669+ git_do push " $ORIGIN " " $release_branch " || dir " Could not push branch '$release_branch ' to remote '$ORIGIN '."
670+ fi
592671 git_do push " $ORIGIN " " $BASE_BRANCH " || die " Could not push branch '$BASE_BRANCH ' to remote '$ORIGIN '."
593672 if noflag notag; then
594673 git_do push --tags " $ORIGIN " || die " Could not push tags to remote '$ORIGIN '."
@@ -633,11 +712,15 @@ T,tagname! Use given tag name
633712 if noflag notag; then
634713 echo " - The hotfix was tagged '$VERSION_PREFIX$TAGNAME '"
635714 fi
636- if [ " $BASE_BRANCH " = " $MASTER_BRANCH " ]; then
715+ if flag cherrypick; then
716+ echo " - All commits from the hotfix branch have been cherry picked into '$DEVELOP_BRANCH '"
717+ elif [ " $BASE_BRANCH " = " $MASTER_BRANCH " ]; then
637718 [ " $commit " = " $BASE_BRANCH " ] && echo " - Master branch '$BASE_BRANCH ' has been back-merged into '$DEVELOP_BRANCH '"
638- [ " $commit " = " $VERSION_PREFIX$TAGNAME " ] && echo " - Hotfix tag '$VERSION_PREFIX$TAGNAME ' has been back-merged into '$DEVELOP_BRANCH '"
719+ [ -n " $release_branch " ] && echo " - Hotfix tag '$VERSION_PREFIX$TAGNAME ' has been back-merged into '$release_branch '"
720+ [ " $commit " = " $VERSION_PREFIX$VERSION " ] && echo " - Hotfix tag '$VERSION_PREFIX$VERSION ' has been back-merged into '$DEVELOP_BRANCH '"
639721 [ " $commit " = " $BRANCH " ] && echo " - Hotfix branch '$BRANCH ' has been merged into '$DEVELOP_BRANCH '"
640722 fi
723+
641724 if noflag keep; then
642725 if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
643726 keepmsg=" has been locally deleted"
0 commit comments