1# $Id$ 2# vim:et:ft=sh:sts=2:sw=2 3# 4# git-flow -- A collection of Git extensions to provide high-level 5# repository operations for Vincent Driessen's branching model. 6# 7# A blog post presenting this model is found at: 8# http://blog.avirtualhome.com/development-workflow-using-git/ 9# 10# Feel free to contribute to this project at: 11# http://github.com/petervanderdoes/gitflow 12# 13# Authors: 14# Copyright 2012-2019 Peter van der Does. All rights reserved. 15# 16# Original Author: 17# Copyright 2010 Vincent Driessen. All rights reserved. 18# 19# Redistribution and use in source and binary forms, with or without 20# modification, are permitted provided that the following conditions are met: 21# 22# 1. Redistributions of source code must retain the above copyright notice, this 23# list of conditions and the following disclaimer. 24# 2. Redistributions in binary form must reproduce the above copyright notice, 25# this list of conditions and the following disclaimer in the documentation 26# and/or other materials provided with the distribution. 27# 28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 29# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 30# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 32# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 33# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 35# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38# 39 40initialize() { 41 require_git_repo 42 require_gitflow_initialized 43 git config --get gitflow.prefix.bugfix >/dev/null 2>&1 || die "Bugfix prefix not set. Please run 'git flow init'." 44 gitflow_load_settings 45 PREFIX=$(git config --get gitflow.prefix.bugfix) 46} 47 48usage() { 49 OPTIONS_SPEC="\ 50git flow bugfix [list] 51git flow bugfix start 52git flow bugfix finish 53git flow bugfix publish 54git flow bugfix track 55git flow bugfix diff 56git flow bugfix rebase 57git flow bugfix checkout 58git flow bugfix pull 59git flow bugfix delete 60 61Manage your bugfix branches. 62 63For more specific help type the command followed by --help 64-- 65" 66 flags_help 67} 68 69cmd_default() { 70 cmd_list "$@" 71} 72 73cmd_list() { 74 OPTIONS_SPEC="\ 75git flow bugfix [list] [-h] [-v] 76 77Lists all the existing bugfix branches in the local repository. 78-- 79h,help! Show this help 80v,verbose Verbose (more) output 81" 82 local bugfix_branches current_branch width branch len 83 local base develop_sha branch_sha 84 85 # Define flags 86 DEFINE_boolean 'verbose' false 'verbose (more) output' v 87 88 # Parse argun=ments 89 parse_args "$@" 90 91 bugfix_branches=$(git_local_branches_prefixed "$PREFIX") 92 if [ -z "$bugfix_branches" ]; then 93 warn "No bugfix branches exist." 94 warn "" 95 warn "You can start a new bugfix branch:" 96 warn "" 97 warn " git flow bugfix start <name> [<base>]" 98 warn "" 99 exit 0 100 fi 101 current_branch=$(git_current_branch) 102 103 # Determine column width first 104 width=0 105 for branch in $bugfix_branches; do 106 len=${#branch} 107 width=$(max $width $len) 108 done 109 width=$(($width+3-${#PREFIX})) 110 111 for branch in $bugfix_branches; do 112 base=$(git merge-base "$branch" "$DEVELOP_BRANCH") 113 develop_sha=$(git rev-parse "$DEVELOP_BRANCH") 114 branch_sha=$(git rev-parse "$branch") 115 if [ "$branch" = "$current_branch" ]; then 116 printf "* " 117 else 118 printf " " 119 fi 120 if flag verbose; then 121 printf "%-${width}s" "${branch#$PREFIX}" 122 if [ "$branch_sha" = "$develop_sha" ]; then 123 printf "(no commits yet)" 124 elif [ "$base" = "$branch_sha" ]; then 125 printf "(is behind develop, may ff)" 126 elif [ "$base" = "$develop_sha" ]; then 127 printf "(based on latest develop)" 128 else 129 printf "(may be rebased)" 130 fi 131 else 132 printf "%s" "${branch#$PREFIX}" 133 fi 134 echo 135 done 136} 137 138cmd_help() { 139 usage 140 exit 0 141} 142 143# Parse arguments and set common variables 144parse_args() { 145 FLAGS "$@" || exit $? 146 eval set -- "${FLAGS_ARGV}" 147 148 # read arguments into global variables 149 if [ -z $1 ]; then 150 NAME='' 151 else 152 NAME=$1 153 fi 154 BRANCH=$PREFIX$NAME 155} 156 157parse_remote_name() { 158 # Parse arguments 159 FLAGS "$@" || exit $? 160 eval set -- "${FLAGS_ARGV}" 161 162 # read arguments into global variables 163 if [ -z $1 ]; then 164 REMOTE='' 165 else 166 REMOTE=$1 167 fi 168 169 if [ -z $2 ]; then 170 NAME='' 171 else 172 NAME=$2 173 fi 174 BRANCH=$PREFIX$NAME 175} 176 177cmd_start() { 178 OPTIONS_SPEC="\ 179git flow bugfix start [-h] [-F] <name> [<base>] 180 181Start new bugfix <name>, optionally basing it on <base> instead of <develop> 182-- 183h,help! Show this help 184showcommands! Show git commands while executing them 185F,[no]fetch Fetch from origin before performing local operation 186" 187 local base 188 189 # Define flags 190 DEFINE_boolean 'fetch' false 'fetch from origin before performing local operation' F 191 192 # Override defaults with values from config 193 gitflow_override_flag_boolean "bugfix.start.fetch" "fetch" 194 195 # Parse arguments 196 parse_args "$@" 197 eval set -- "${FLAGS_ARGV}" 198 base=${2:-$DEVELOP_BRANCH} 199 200 require_base_is_local_branch "$base" 201 gitflow_require_name_arg 202 203 # Update the local repo with remote changes, if asked 204 if flag fetch; then 205 git_fetch_branch "$ORIGIN" "$base" 206 fi 207 208 # Sanity checks 209 require_branch_absent "$BRANCH" 210 211 # If the origin branch counterpart exists, assert that the local branch 212 # isn't behind it (to avoid unnecessary rebasing) 213 if git_remote_branch_exists "$ORIGIN/$base"; then 214 require_branches_equal "$base" "$ORIGIN/$base" 215 fi 216 217 run_pre_hook "$NAME" "$ORIGIN" "$BRANCH" "$base" 218 219 gitflow_config_set_base_branch $base $BRANCH 220 221 # create branch 222 git_do checkout -b "$BRANCH" "$base" || die "Could not create bugfix branch '$BRANCH'." 223 224 run_post_hook "$NAME" "$ORIGIN" "$BRANCH" "$base" 225 226 echo 227 echo "Summary of actions:" 228 echo "- A new branch '$BRANCH' was created, based on '$base'" 229 echo "- You are now on branch '$(git_current_branch)'" 230 echo "" 231 echo "Now, start committing on your bugfix. When done, use:" 232 echo "" 233 echo " git flow bugfix finish $NAME" 234 echo 235} 236 237cmd_finish() { 238 OPTIONS_SPEC="\ 239git flow bugfix finish [-h] [-F] [-r] [-p] [-k] [-D] [-S] [--no-ff] <name|nameprefix> 240 241Finish bugfix <name> 242-- 243h,help! Show this help 244showcommands! Show git commands while executing them 245F,[no]fetch Fetch from origin before performing finish 246r,[no]rebase Rebase before merging 247p,[no]preserve-merges Preserve merges while rebasing 248[no]push Push to origin after performing finish 249k,[no]keep Keep branch after performing finish 250keepremote! Keep the remote branch 251keeplocal! Keep the local branch 252D,[no]force_delete Force delete bugfix branch after finish 253S,[no]squash Squash bugfix during merge 254no-ff! Never fast-forward during the merge 255" 256 local finish_base 257 258 # Define flags 259 DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F 260 DEFINE_boolean 'rebase' false "rebase before merging" r 261 DEFINE_boolean 'preserve-merges' false 'try to recreate merges while rebasing' p 262 DEFINE_boolean 'push' false "push to $ORIGIN after performing finish" 263 DEFINE_boolean 'keep' false "keep branch after performing finish" k 264 DEFINE_boolean 'keepremote' false "keep the remote branch" 265 DEFINE_boolean 'keeplocal' false "keep the local branch" 266 DEFINE_boolean 'force_delete' false "force delete bugfix branch after finish" D 267 DEFINE_boolean 'squash' false "squash bugfix during merge" S 268 DEFINE_boolean 'squash-info' false "add branch info during squash" 269 DEFINE_boolean 'no-ff!' false "Don't fast-forward ever during merge " 270 271 # Override defaults with values from config 272 gitflow_override_flag_boolean "bugfix.finish.fetch" "fetch" 273 gitflow_override_flag_boolean "bugfix.finish.rebase" "rebase" 274 gitflow_override_flag_boolean "bugfix.finish.preserve-merges" "preserve_merges" 275 gitflow_override_flag_boolean "bugfix.finish.push" "push" 276 gitflow_override_flag_boolean "bugfix.finish.keep" "keep" 277 gitflow_override_flag_boolean "bugfix.finish.keepremote" "keepremote" 278 gitflow_override_flag_boolean "bugfix.finish.keeplocal" "keeplocal" 279 gitflow_override_flag_boolean "bugfix.finish.force-delete" "force_delete" 280 gitflow_override_flag_boolean "bugfix.finish.squash" "squash" 281 gitflow_override_flag_boolean "bugfix.finish.squash-info" "squash_info" 282 gitflow_override_flag_boolean "bugfix.finish.no-ff" "no_ff" 283 284 # Parse arguments 285 parse_args "$@" 286 287 # Use current branch if no name is given 288 if [ "$NAME" = "" ]; then 289 gitflow_use_current_branch_name 290 fi 291 292 # Keeping both branches implies the --keep flag to be true. 293 if flag keepremote && flag keeplocal; then 294 FLAGS_keep=$FLAGS_TRUE 295 fi 296 297 # Sanity checks 298 require_branch "$BRANCH" 299 300 BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH) 301 BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH} 302 git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't finish the bugfix branch '$BRANCH'." 303 304 # Detect if we're restoring from a merge conflict 305 if [ -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE" ]; then 306 # 307 # TODO: detect that we're working on the correct branch here! 308 # The user need not necessarily have given the same $NAME twice here 309 # (although he/she should). 310 # 311 312 # TODO: git_is_clean_working_tree() should provide an alternative 313 # exit code for "unmerged changes in working tree", which we should 314 # actually be testing for here 315 if git_is_clean_working_tree; then 316 finish_base=$(cat "$DOT_GIT_DIR/.gitflow/MERGE_BASE") 317 318 # Since the working tree is now clean, either the user did a 319 # successful merge manually, or the merge was cancelled. 320 # We detect this using git_is_branch_merged_into() 321 if git_is_branch_merged_into "$BRANCH" "$finish_base"; then 322 rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE" 323 helper_finish_cleanup 324 exit 0 325 else 326 # If the user cancelled the merge and decided to wait until 327 # later,that's fine. But we have to acknowledge this by 328 # removing the MERGE_BASE file and continuing normal execution 329 # of the finish 330 rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE" 331 fi 332 else 333 echo 334 echo "Merge conflicts not resolved yet, use:" 335 echo " git mergetool" 336 echo " git commit" 337 echo 338 echo "You can then complete the finish by running it again:" 339 echo " git flow bugfix finish $NAME" 340 echo 341 exit 1 342 fi 343 fi 344 345 # Sanity checks 346 require_clean_working_tree 347 348 # We always fetch the Branch from Origin 349 # This is done to avoid possible commits on the remote that are not 350 # merged into the local branch 351 if git_remote_branch_exists "$ORIGIN/$BRANCH"; then 352 git_fetch_branch "$ORIGIN" "$BRANCH" 353 fi 354 355 # Update local branches with remote branches 356 if flag fetch; then 357 git_fetch_branch "$ORIGIN" "$BASE_BRANCH" 358 fi 359 360 # Check if the local branches have all the commits from the remote branches 361 if git_remote_branch_exists "$ORIGIN/$BRANCH"; then 362 require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH" 363 fi 364 if git_remote_branch_exists "$ORIGIN/$BASE_BRANCH"; then 365 require_branches_equal "$BASE_BRANCH" "$ORIGIN/$BASE_BRANCH" 366 fi 367 368 run_pre_hook "$NAME" "$ORIGIN" "$BRANCH" 369 370 # If the user wants to rebase, do that first 371 if flag rebase; then 372 local _rebase_opts="" 373 if flag preserve_merges; then 374 _rebase_opts="$_rebase_opts -p" 375 fi 376 if flag showcommands; then 377 _rebase_opts="$_rebase_opts --showcommands" 378 fi 379 if ! git flow bugfix rebase $_rebase_opts "$NAME"; then 380 warn "Finish was aborted due to conflicts during rebase." 381 warn "Please finish the rebase manually now." 382 warn "When finished, re-run:" 383 warn " git flow bugfix finish '$NAME' '$BASE_BRANCH'" 384 exit 1 385 fi 386 fi 387 388 # Merge into BASE 389 git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'." 390 391 if noflag squash; then 392 if flag no_ff; then 393 git_do merge --no-ff "$BRANCH" 394 else 395 if [ "$(git rev-list -n2 "$BASE_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then 396 git_do merge --ff "$BRANCH" 397 else 398 git_do merge --no-ff "$BRANCH" 399 fi 400 fi 401 else 402 git_do merge --squash "$BRANCH" 403 flag squash_info && gitflow_create_squash_message "Merged bugfix branch '$BRANCH'" "$BASE_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG" 404 git_do commit 405 fi 406 407 if [ $? -ne 0 ]; then 408 # Oops.. we have a merge conflict! 409 # Write the given $BASE_BRANCH to a temporary file as we will 410 # be needing it later. 411 mkdir -p "$DOT_GIT_DIR/.gitflow" 412 echo "$BASE_BRANCH" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE" 413 echo 414 echo "There were merge conflicts. To resolve the merge conflict manually, use:" 415 echo " git mergetool" 416 echo " git commit" 417 echo 418 echo "You can then complete the finish by running it again:" 419 echo " git flow bugfix finish $NAME" 420 echo 421 exit 1 422 fi 423 424 run_post_hook "$NAME" "$ORIGIN" "$BRANCH" 425 426 # When no merge conflict is detected, just clean up the bugfix branch 427 gitflow_config_remove_base_branch "$BRANCH" 428 helper_finish_cleanup 429} 430 431helper_finish_cleanup() { 432 local keepmsg remotebranchdeleted localbranchdeleted 433 434 # Sanity checks 435 require_branch "$BRANCH" 436 require_clean_working_tree 437 438 remotebranchdeleted=$FLAGS_FALSE 439 localbranchdeleted=$FLAGS_FALSE 440 441 if flag push; then 442 git_do push "$ORIGIN" "$BASE_BRANCH" || die "Could not push branch '$BASE_BRANCH' to remote '$ORIGIN'." 443 fi 444 445 if noflag keep; then 446 447 # Always delete remote first 448 if noflag keepremote;then 449 if git_remote_branch_exists "$ORIGIN/$BRANCH"; then 450 git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE 451 fi 452 fi 453 454 # Delete local after remote to avoid warnings 455 if noflag keeplocal; then 456 if [ "$BRANCH" = "$(git_current_branch)" ]; then 457 git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'." 458 fi 459 if flag force_delete; then 460 git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE 461 else 462 if noflag squash; then 463 git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE 464 else 465 git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE 466 fi 467 fi 468 fi 469 470 # no more branches: we can safely remove config section 471 if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then 472 gitflow_config_remove_base_section "$BRANCH" 473 fi 474 fi 475 476 echo 477 echo "Summary of actions:" 478 echo "- The bugfix branch '$BRANCH' was merged into '$BASE_BRANCH'" 479 #echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported 480 if noflag keep; then 481 if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then 482 keepmsg="has been locally deleted" 483 else 484 keepmsg="is still locally available" 485 fi 486 if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then 487 keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'" 488 elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then 489 keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'" 490 fi 491 else 492 keepmsg="is still locally available" 493 if git_remote_branch_exists "$ORIGIN/$BRANCH"; then 494 keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'" 495 fi 496 fi 497 echo "- bugfix branch '$BRANCH' "$keepmsg 498 echo "- You are now on branch '$(git_current_branch)'" 499 echo 500} 501 502cmd_publish() { 503 OPTIONS_SPEC="\ 504git flow bugfix publish [-h] [<name>] 505 506Publish bugfix branch <name> on $ORIGIN. 507When <name> is omitted the current branch is used, but only if it's a bugfix branch. 508-- 509h,help! Show this help 510showcommands! Show git commands while executing them 511" 512 # Parse arguments 513 parse_args "$@" 514 515 # Use current branch if no name is given 516 if [ "$NAME" = "" ]; then 517 gitflow_use_current_branch_name 518 fi 519 520 521 # Sanity checks 522 require_clean_working_tree 523 require_branch "$BRANCH" 524 git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'." 525 require_branch_absent "$ORIGIN/$BRANCH" 526 527 run_pre_hook "$NAME" "$ORIGIN" "$BRANCH" 528 529 # Create remote branch with remote tracking 530 git_do push -u "$ORIGIN" "$BRANCH:$BRANCH" 531 git_do fetch -q "$ORIGIN" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'." 532 git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'." 533 534 run_post_hook "$NAME" "$ORIGIN" "$BRANCH" 535 536 echo 537 echo "Summary of actions:" 538 echo "- The remote branch '$BRANCH' was created or updated" 539 echo "- The local branch '$BRANCH' was configured to track the remote branch" 540 echo "- You are now on branch '$(git_current_branch)'" 541 echo 542} 543 544cmd_track() { 545 OPTIONS_SPEC="\ 546git flow bugfix track [-h] <name> 547 548Start tracking bugfix <name> that is shared on $ORIGIN 549-- 550h,help! Show this help 551showcommands! Show git commands while executing them 552" 553 # Parse arguments 554 parse_args "$@" 555 556 gitflow_require_name_arg 557 558 # Sanity checks 559 require_clean_working_tree 560 require_local_branch_absent "$BRANCH" 561 562 run_pre_hook "$NAME" "$ORIGIN" "$BRANCH" 563 564 git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'." 565 git_remote_branch_exists "$ORIGIN/$BRANCH" 566 567 # Create tracking branch 568 git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH" || die "Could not create '$BRANCH'." 569 570 run_post_hook "$NAME" "$ORIGIN" "$BRANCH" 571 572 echo 573 echo "Summary of actions:" 574 echo "- A new remote tracking branch '$BRANCH' was created" 575 echo "- You are now on branch '$(git_current_branch)'" 576 echo 577} 578 579cmd_diff() { 580 OPTIONS_SPEC="\ 581git flow bugfix diff [-h] [<name|nameprefix>] 582 583Show all changes in <name> that are not in the base 584-- 585h,help! Show this help 586showcommands! Show git commands while executing them 587" 588 local base 589 590 # Parse arguments 591 parse_args "$@" 592 593 # Use current branch if no name is given 594 if [ "$NAME" = "" ]; then 595 gitflow_use_current_branch_name 596 fi 597 598 base=$(gitflow_config_get_base_branch $BRANCH) 599 base=${base:-$DEVELOP_BRANCH} 600 601 git_do diff "$base...$BRANCH" 602} 603 604cmd_checkout() { 605 OPTIONS_SPEC="\ 606git flow bugfix checkout [-h] [<name|nameprefix>] 607 608Switch to bugfix branch <name> 609-- 610h,help! Show this help 611showcommands! Show git commands while executing them 612" 613 # Parse arguments 614 parse_args "$@" 615 616 NAME=$(gitflow_resolve_nameprefix "$NAME" "$PREFIX") 617 if [ $? -eq 0 ]; then 618 BRANCH=$PREFIX$NAME 619 git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'." 620 fi 621} 622 623cmd_co() { 624 # Alias for checkout 625 cmd_checkout "$@" 626} 627 628cmd_rebase() { 629 OPTIONS_SPEC="\ 630git flow bugfix rebase [-h] [-i] [-p] [<name|nameprefix>] 631 632Rebase <name> on <base_branch> 633-- 634h,help! Show this help 635showcommands! Show git commands while executing them 636i,[no]interactive Do an interactive rebase 637p,[no]preserve-merges Preserve merges 638" 639 local opts 640 641 # Define flags 642 DEFINE_boolean 'interactive' false 'do an interactive rebase' i 643 DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p 644 645 # Override defaults with values from config 646 gitflow_override_flag_boolean "bugfix.rebase.interactive" "interactive" 647 gitflow_override_flag_boolean "bugfix.rebase.preserve-merges" "preserve_merges" 648 649 # Parse arguments 650 parse_args "$@" 651 652 # Use current branch if no name is given 653 if [ "$NAME" = "" ]; then 654 gitflow_use_current_branch_name 655 fi 656 657 658 BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH) 659 BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH} 660 661 warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..." 662 if ! git_config_bool_exists "rebase.autostash"; then 663 require_clean_working_tree 664 fi 665 require_branch "$BRANCH" 666 667 git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the bugfix branch '$BRANCH'." 668 669 git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'." 670 if flag interactive; then 671 opts="$opts -i" 672 fi 673 if flag preserve_merges; then 674 opts="$opts -p" 675 fi 676 git_do rebase $opts "$BASE_BRANCH" 677} 678 679avoid_accidental_cross_branch_action() { 680 local current_branch 681 682 current_branch=$(git_current_branch) 683 if [ "$BRANCH" != "$current_branch" ]; then 684 warn "Trying to pull from '$BRANCH' while currently on branch '$current_branch'." 685 warn "To avoid unintended merges, git-flow aborted." 686 return 1 687 fi 688 return 0 689} 690 691cmd_pull() { 692 OPTIONS_SPEC="\ 693git flow bugfix pull [-h] <remote> [<name>] 694 695Pull bugfix <name> from <remote> 696-- 697h,help! Show this help 698showcommands! Show git commands while executing them 699" 700 local current_branch 701 702 # Define flags 703 DEFINE_boolean 'rebase' false "pull with rebase" r 704 705 warn "The command 'git flow bugfix pull' will be deprecated per version 2.0.0. Use 'git flow bugfix track' instead." 706 707 # Parse arguments 708 parse_remote_name "$@" 709 710 if [ -z "$REMOTE" ]; then 711 die "Name a remote explicitly." 712 fi 713 714 # Use current branch if no name is given 715 if [ "$NAME" = "" ]; then 716 gitflow_use_current_branch_name 717 fi 718 719 # To avoid accidentally merging different bugfix branches into each other, 720 # die if the current bugfix branch differs from the requested $NAME 721 # argument. 722 current_branch=$(git_current_branch) 723 if startswith "$current_branch" "$PREFIX"; then 724 # We are on a local bugfix branch already, so $BRANCH must be equal to 725 # the current branch 726 avoid_accidental_cross_branch_action || die 727 fi 728 729 require_clean_working_tree 730 731 run_pre_hook "$NAME" "$REMOTE" "$BRANCH" 732 733 if git_local_branch_exists "$BRANCH"; then 734 # Again, avoid accidental merges 735 avoid_accidental_cross_branch_action || die 736 737 # We already have a local branch called like this, so simply pull the 738 # remote changes in 739 if flag rebase; then 740 if ! git_do pull --rebase -q "$REMOTE" "$BRANCH"; then 741 warn "Pull was aborted. There might be conflicts during rebase or '$REMOTE' might be inaccessible." 742 exit 1 743 fi 744 else 745 git_do pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'." 746 fi 747 748 echo "Pulled $REMOTE's changes into $BRANCH." 749 else 750 # Setup the local branch clone for the first time 751 git_do fetch -q "$REMOTE" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$REMOTE'." # Stores in FETCH_HEAD 752 git_do branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed." 753 git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'." 754 echo "Created local branch $BRANCH based on $REMOTE's $BRANCH." 755 fi 756 757 run_post_hook "$NAME" "$REMOTE" "$BRANCH" 758} 759 760cmd_delete() { 761 OPTIONS_SPEC="\ 762git flow bugfix delete [-h] [-f] [-r] <name> 763 764Delete a given bugfix branch 765-- 766h,help! Show this help 767showcommands! Show git commands while executing them 768f,[no]force Force deletion 769r,[no]remote Delete remote branch 770" 771 local current_branch 772 773 # Define flags 774 DEFINE_boolean 'force' false "force deletion" f 775 DEFINE_boolean 'remote' false "delete remote branch" r 776 777 # Override defaults with values from config 778 gitflow_override_flag_boolean "bugfix.delete.force" "force" 779 gitflow_override_flag_boolean "bugfix.delete.remote" "remote" 780 781 # Parse arguments 782 parse_args "$@" 783 784 gitflow_require_name_arg 785 786 # Sanity checks 787 require_branch "$BRANCH" 788 789 BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH) 790 BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH} 791 792 run_pre_hook "$NAME" "$ORIGIN" "$BRANCH" 793 794 current_branch=$(git_current_branch) 795 # We can't delete a branch we are on, switch to the develop branch. 796 if [ "$BRANCH" = "$current_branch" ]; then 797 require_clean_working_tree 798 if git_local_branch_exists "$BASE_BRANCH"; then 799 git_do checkout "$BASE_BRANCH" 800 else 801 git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'." 802 fi 803 fi 804 805 if git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then 806 git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH." 807 if flag remote; then 808 git_remote_branch_delete "$BRANCH" 809 fi 810 else 811 if flag force; then 812 git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH." 813 if flag remote; then 814 git_remote_branch_delete "$BRANCH" 815 fi 816 else 817 die "bugfix branch '$BRANCH' has been not been merged yet. Use -f to force the deletion." 818 fi 819 fi 820 821 gitflow_config_remove_base_section "$BRANCH" 822 run_post_hook "$NAME" "$ORIGIN" "$BRANCH" 823 824 echo 825 echo "Summary of actions:" 826 echo "- bugfix branch '$BRANCH' has been deleted." 827 flag remote && echo "- bugfix branch '$BRANCH' in '$ORIGIN' has been deleted." 828 echo "- You are now on branch '$(git_current_branch)'" 829 echo 830} 831 832cmd_rename() { 833 OPTIONS_SPEC="\ 834git flow bugfix rename <new_name> [<new_name>] 835 836Rename a given bugfix branch 837-- 838h,help! Show this help 839showcommands! Show git commands while executing them 840" 841 gitflow_rename_branch "$@" 842} 843