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.feature >/dev/null 2>&1 || die "Feature prefix not set. Please run 'git flow init'."
44	gitflow_load_settings
45	PREFIX=$(git config --get gitflow.prefix.feature)
46}
47
48usage() {
49	OPTIONS_SPEC="\
50git flow feature [list]
51git flow feature start
52git flow feature finish
53git flow feature publish
54git flow feature track
55git flow feature diff
56git flow feature rebase
57git flow feature checkout
58git flow feature pull
59git flow feature delete
60
61Manage your feature 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 feature [list] [-h] [-v]
76
77Lists all the existing feature branches in the local repository.
78--
79h,help!     Show this help
80v,verbose   Verbose (more) output
81"
82	local feature_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	feature_branches=$(git_local_branches_prefixed "$PREFIX")
92	if [ -z "$feature_branches" ]; then
93		warn "No feature branches exist."
94		warn ""
95		warn "You can start a new feature branch:"
96		warn ""
97		warn "    git flow feature 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 $feature_branches; do
106		len=${#branch}
107		width=$(max $width $len)
108	done
109	width=$(($width+3-${#PREFIX}))
110
111	for branch in $feature_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 feature start [-h] [-F] <name> [<base>]
180
181Start new feature <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   "feature.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 feature 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 feature. When done, use:"
232	echo ""
233	echo "     git flow feature finish $NAME"
234	echo
235}
236
237cmd_finish() {
238	OPTIONS_SPEC="\
239git flow feature finish [-h] [-F] [-r] [-p] [-k] [-D] [-S] [--no-ff] <name|nameprefix>
240
241Finish feature <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 feature branch after finish
253S,[no]squash           Squash feature 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 feature branch after finish" D
267	DEFINE_boolean 'squash' false "squash feature 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   "feature.finish.fetch"             "fetch"
273	gitflow_override_flag_boolean   "feature.finish.rebase"            "rebase"
274	gitflow_override_flag_boolean   "feature.finish.preserve-merges"   "preserve_merges"
275	gitflow_override_flag_boolean   "feature.finish.push"              "push"
276	gitflow_override_flag_boolean   "feature.finish.keep"              "keep"
277	gitflow_override_flag_boolean   "feature.finish.keepremote"        "keepremote"
278	gitflow_override_flag_boolean   "feature.finish.keeplocal"         "keeplocal"
279	gitflow_override_flag_boolean   "feature.finish.force-delete"      "force_delete"
280	gitflow_override_flag_boolean   "feature.finish.squash"            "squash"
281	gitflow_override_flag_boolean   "feature.finish.squash-info"       "squash_info"
282	gitflow_override_flag_boolean   "feature.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 feature 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 feature 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 feature 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 feature 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 feature 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 feature 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 feature 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 feature 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 "- Feature branch '$BRANCH' "$keepmsg
498	echo "- You are now on branch '$(git_current_branch)'"
499	echo
500}
501
502cmd_publish() {
503	OPTIONS_SPEC="\
504git flow feature publish [-h] [<name>]
505
506Publish feature branch <name> on $ORIGIN.
507When <name> is omitted the current branch is used, but only if it's a feature 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 feature track [-h] <name>
547
548Start tracking feature <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 feature 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 feature checkout [-h] [<name|nameprefix>]
607
608Switch to feature 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 feature 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   "feature.rebase.interactive"       "interactive"
647	gitflow_override_flag_boolean   "feature.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
666	require_branch "$BRANCH"
667
668	git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the feature branch '$BRANCH'."
669
670	git_do checkout -q "$BRANCH"  || die "Could not check out branch '$BRANCH'."
671	if flag interactive; then
672		opts="$opts -i"
673	fi
674	if flag preserve_merges; then
675		opts="$opts -p"
676	fi
677	git_do rebase $opts "$BASE_BRANCH"
678}
679
680avoid_accidental_cross_branch_action() {
681	local current_branch
682
683	current_branch=$(git_current_branch)
684	if [ "$BRANCH" != "$current_branch" ]; then
685		warn "Trying to pull from '$BRANCH' while currently on branch '$current_branch'."
686		warn "To avoid unintended merges, git-flow aborted."
687		return 1
688	fi
689	return 0
690}
691
692cmd_pull() {
693	OPTIONS_SPEC="\
694git flow feature pull [-h] <remote> [<name>]
695
696Pull feature <name> from <remote>
697--
698h,help!          Show this help
699showcommands!    Show git commands while executing them
700"
701	local current_branch
702
703	# Define flags
704	DEFINE_boolean 'rebase' false "pull with rebase" r
705
706	warn "The command 'git flow feature pull' will be deprecated per version 2.0.0. Use 'git flow feature track' instead."
707
708	# Parse arguments
709	parse_remote_name "$@"
710
711	if [ -z "$REMOTE" ]; then
712		die "Name a remote explicitly."
713	fi
714
715	# Use current branch if no name is given
716	if [ "$NAME" = "" ]; then
717		gitflow_use_current_branch_name
718	fi
719
720	# To avoid accidentally merging different feature branches into each other,
721	# die if the current feature branch differs from the requested $NAME
722	# argument.
723	current_branch=$(git_current_branch)
724	if startswith "$current_branch" "$PREFIX"; then
725		# We are on a local feature branch already, so $BRANCH must be equal to
726		# the current branch
727		avoid_accidental_cross_branch_action || die
728	fi
729
730	require_clean_working_tree
731
732	run_pre_hook "$NAME" "$REMOTE" "$BRANCH"
733
734	if git_local_branch_exists "$BRANCH"; then
735		# Again, avoid accidental merges
736		avoid_accidental_cross_branch_action || die
737
738		# We already have a local branch called like this, so simply pull the
739		# remote changes in
740		if flag rebase; then
741			if ! git_do pull --rebase -q "$REMOTE" "$BRANCH"; then
742				warn "Pull was aborted. There might be conflicts during rebase or '$REMOTE' might be inaccessible."
743				exit 1
744			fi
745		else
746			git_do pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'."
747		fi
748
749		echo "Pulled $REMOTE's changes into $BRANCH."
750	else
751		# Setup the local branch clone for the first time
752		git_do fetch -q "$REMOTE" "$BRANCH" ||  die "Could not fetch branch '$BRANCH' from remote '$REMOTE'."     # Stores in FETCH_HEAD
753		git_do branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed."
754		git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
755		echo "Created local branch $BRANCH based on $REMOTE's $BRANCH."
756	fi
757
758	run_post_hook "$NAME" "$REMOTE" "$BRANCH"
759}
760
761cmd_delete() {
762	OPTIONS_SPEC="\
763git flow feature delete [-h] [-f] [-r] <name>
764
765Delete a given feature branch
766--
767h,help!          Show this help
768showcommands!    Show git commands while executing them
769f,[no]force      Force deletion
770r,[no]remote     Delete remote branch
771"
772	local current_branch
773
774	# Define flags
775	DEFINE_boolean 'force' false "force deletion" f
776	DEFINE_boolean 'remote' false "delete remote branch" r
777
778	# Override defaults with values from config
779	gitflow_override_flag_boolean   "feature.delete.force"    "force"
780	gitflow_override_flag_boolean   "feature.delete.remote"   "remote"
781
782	# Parse arguments
783	parse_args "$@"
784
785	gitflow_require_name_arg
786
787	# Sanity checks
788	require_branch "$BRANCH"
789
790	BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
791	BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
792
793	run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
794
795	current_branch=$(git_current_branch)
796	# We can't delete a branch we are on, switch to the develop branch.
797	if [ "$BRANCH" = "$current_branch" ]; then
798		require_clean_working_tree
799		if git_local_branch_exists "$BASE_BRANCH"; then
800			git_do checkout "$BASE_BRANCH"
801		else
802			git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
803		fi
804	fi
805
806	if git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
807		git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH."
808		if flag remote; then
809			git_remote_branch_delete "$BRANCH"
810		fi
811	else
812		if flag force; then
813			git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH."
814			if flag remote; then
815				git_remote_branch_delete "$BRANCH"
816			fi
817		else
818			die "Feature branch '$BRANCH' has been not been merged yet. Use -f to force the deletion."
819		fi
820	fi
821
822	gitflow_config_remove_base_section "$BRANCH"
823	run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
824
825	echo
826	echo "Summary of actions:"
827	echo "- Feature branch '$BRANCH' has been deleted."
828	flag remote && echo "- Feature branch '$BRANCH' in '$ORIGIN' has been deleted."
829	echo "- You are now on branch '$(git_current_branch)'"
830	echo
831}
832
833cmd_rename() {
834	OPTIONS_SPEC="\
835git flow feature rename <new_name> [<new_name>]
836
837Rename a given feature branch
838--
839h,help!          Show this help
840showcommands!    Show git commands while executing them
841"
842	gitflow_rename_branch "$@"
843}
844