Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added functionality around `git flow project` for creating projects. #272

Open
wants to merge 15 commits into from

3 participants

@erasmusa

No description provided.

Changes.mdown
@@ -1,3 +1,17 @@
+0.4.3:
+-----
+Release: **not yet**
+
+* Added `git flow project` based on `git flow feature` for branches that
+ typically lives longer than 1 day.
+
+* Changes `git flow feature finish` to accept a base branch in order to finish
+ features initially created from a project branch.
+
+* Cahnged `git flow init` to ask the user what the project branches prefixes should
@m14t
m14t added a note

Typo Cahnged -> Changed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 19, 2010
  1. Merge branch 'hotfix/0.2.1'

    authored
Commits on Jul 22, 2010
  1. Merge branch 'release/0.3'

    authored
Commits on Oct 18, 2010
  1. Merge branch 'release/0.4'

    authored
Commits on Feb 14, 2011
  1. Merge branch 'release/0.4.1'

    authored
Commits on Oct 24, 2012
Commits on Oct 25, 2012
  1. Merge branch 'develop'

    Adriaan Erasmus authored
  2. Fixed git-flow-init

    Adriaan Erasmus authored
  3. Merge branch 'develop'

    Adriaan Erasmus authored
Commits on Oct 28, 2012
  1. Spelling mistake fix

    Adriaan Erasmus authored
  2. Updated makefile

    Adriaan Erasmus authored
  3. @erasmusa
  4. @erasmusa
  5. @erasmusa

    Added .gitignore

    erasmusa authored
  6. @erasmusa

    Fixed .gitignore

    erasmusa authored
  7. @erasmusa

    Merge branch 'develop'

    erasmusa authored
    Conflicts:
    	.gitignore
This page is out of date. Refresh to see the latest.
View
1  .gitignore
@@ -2,3 +2,4 @@ debian/files
debian/*.substvars
debian/*.debhelper.log
debian/*/*
+howto_install.txt
View
14 Changes.mdown
@@ -1,3 +1,17 @@
+0.4.3:
+-----
+Release: **not yet**
+
+* Added `git flow project` based on `git flow feature` for branches that
+ typically lives longer than 1 day.
+
+* Changed `git flow feature finish` to accept a base branch in order to finish
+ features initially created from a project branch.
+
+* Changed `git flow init` to ask the user what the project branches prefixes should
+ be called.
+
+
0.4.2:
-----
Release date: **not yet**
View
1  Makefile
@@ -34,6 +34,7 @@ EXEC_FILES=git-flow
# files that need mode 644
SCRIPT_FILES =git-flow-init
+SCRIPT_FILES+=git-flow-project
SCRIPT_FILES+=git-flow-feature
SCRIPT_FILES+=git-flow-hotfix
SCRIPT_FILES+=git-flow-release
View
2  contrib/gitflow-installer.sh
@@ -21,7 +21,7 @@ if [ -z "$REPO_HOME" ] ; then
fi
EXEC_FILES="git-flow"
-SCRIPT_FILES="git-flow-init git-flow-feature git-flow-hotfix git-flow-release git-flow-support git-flow-version gitflow-common gitflow-shFlags"
+SCRIPT_FILES="git-flow-init git-flow-project git-flow-feature git-flow-hotfix git-flow-release git-flow-support git-flow-version gitflow-common gitflow-shFlags"
SUBMODULE_FILE="gitflow-shFlags"
echo "### gitflow no-make installer ###"
View
1  git-flow
@@ -54,6 +54,7 @@ usage() {
echo
echo "Available subcommands are:"
echo " init Initialize a new git repo with support for the branching model."
+ echo " project Manage your project branches."
echo " feature Manage your feature branches."
echo " release Manage your release branches."
echo " hotfix Manage your hotfix branches."
View
87 git-flow-feature
@@ -204,7 +204,7 @@ cmd_start() {
# update the local repo with remote changes, if asked
if flag fetch; then
- git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
+ git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
fi
# if the origin branch counterpart exists, assert that the local branch
@@ -214,7 +214,7 @@ cmd_start() {
fi
# create branch
- if ! git_do checkout -b "$BRANCH" "$BASE"; then
+ if ! git checkout -b "$BRANCH" "$BASE"; then
die "Could not create feature branch '$BRANCH'"
fi
@@ -225,7 +225,7 @@ cmd_start() {
echo ""
echo "Now, start committing on your feature. When done, use:"
echo ""
- echo " git flow feature finish $NAME"
+ echo " git flow feature finish $NAME $BASE"
echo
}
@@ -236,6 +236,7 @@ cmd_finish() {
DEFINE_boolean force_delete false "force delete feature branch after finish" D
DEFINE_boolean squash false "squash feature during merge" S
parse_args "$@"
+ BASE=${2:-$DEVELOP_BRANCH}
expand_nameprefix_arg_or_current
# sanity checks
@@ -287,40 +288,47 @@ cmd_finish() {
# update local repo with remote changes first, if asked
if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
if flag fetch; then
- git_do fetch -q "$ORIGIN" "$BRANCH"
- git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
+ git fetch -q "$ORIGIN" "$BRANCH"
+ #git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
+ git fetch -q "$ORIGIN" "$BASE"
fi
fi
if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
fi
- if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
- require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+ #if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
+ if has "$ORIGIN/$BASE" $(git_remote_branches); then
+ #require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+ require_branches_equal "$BASE" "$ORIGIN/$BASE"
fi
# if the user wants to rebase, do that first
if flag rebase; then
- if ! git flow feature rebase "$NAME" "$DEVELOP_BRANCH"; then
+ #if ! git flow feature rebase "$NAME" "$DEVELOP_BRANCH"; then
+ if ! git flow feature rebase "$NAME" "$BASE"; then
warn "Finish was aborted due to conflicts during rebase."
warn "Please finish the rebase manually now."
warn "When finished, re-run:"
- warn " git flow feature finish '$NAME' '$DEVELOP_BRANCH'"
+ #warn " git flow feature finish '$NAME' '$DEVELOP_BRANCH'"
+ warn " git flow feature finish '$NAME' '$BASE'"
exit 1
fi
fi
# merge into BASE
- git_do checkout "$DEVELOP_BRANCH"
- if [ "$(git rev-list -n2 "$DEVELOP_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then
- git_do merge --ff "$BRANCH"
+ #git checkout "$DEVELOP_BRANCH"
+ git checkout "$BASE"
+ #if [ "$(git rev-list -n2 "$DEVELOP_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then
+ if [ "$(git rev-list -n2 "$BASE..$BRANCH" | wc -l)" -eq 1 ]; then
+ git merge --ff "$BRANCH"
else
if noflag squash; then
- git_do merge --no-ff "$BRANCH"
+ git merge --no-ff "$BRANCH"
else
- git_do merge --squash "$BRANCH"
- git_do commit
- git_do merge "$BRANCH"
+ git merge --squash "$BRANCH"
+ git commit
+ git merge "$BRANCH"
fi
fi
@@ -328,7 +336,8 @@ cmd_finish() {
# oops.. we have a merge conflict!
# write the given $DEVELOP_BRANCH to a temporary file (we need it later)
mkdir -p "$DOT_GIT_DIR/.gitflow"
- echo "$DEVELOP_BRANCH" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
+ #echo "$DEVELOP_BRANCH" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
+ echo "$BASE" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
echo
echo "There were merge conflicts. To resolve the merge conflict manually, use:"
echo " git mergetool"
@@ -351,28 +360,30 @@ helper_finish_cleanup() {
# delete branch
if flag fetch; then
- git_do push "$ORIGIN" ":refs/heads/$BRANCH"
+ git push "$ORIGIN" ":refs/heads/$BRANCH"
fi
if noflag keep; then
if flag force_delete; then
- git_do branch -D "$BRANCH"
+ git branch -D "$BRANCH"
else
- git_do branch -d "$BRANCH"
+ git branch -d "$BRANCH"
fi
fi
echo
echo "Summary of actions:"
- echo "- The feature branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
+ #echo "- The feature branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
+ echo "- The feature branch '$BRANCH' was merged into '$BASE'"
#echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported
if flag keep; then
echo "- Feature branch '$BRANCH' is still available"
else
echo "- Feature branch '$BRANCH' has been removed"
fi
- echo "- You are now on branch '$DEVELOP_BRANCH'"
+ #echo "- You are now on branch '$DEVELOP_BRANCH'"
+ echo "- You are now on branch '$BASE'"
echo
}
@@ -383,17 +394,17 @@ cmd_publish() {
# sanity checks
require_clean_working_tree
require_branch "$BRANCH"
- git_do fetch -q "$ORIGIN"
+ git fetch -q "$ORIGIN"
require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
- git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
- git_do fetch -q "$ORIGIN"
+ git push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
+ git fetch -q "$ORIGIN"
# configure remote tracking
- git_do config "branch.$BRANCH.remote" "$ORIGIN"
- git_do config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
- git_do checkout "$BRANCH"
+ git config "branch.$BRANCH.remote" "$ORIGIN"
+ git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
+ git checkout "$BRANCH"
echo
echo "Summary of actions:"
@@ -410,11 +421,11 @@ cmd_track() {
# sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
- git_do fetch -q "$ORIGIN"
+ git fetch -q "$ORIGIN"
require_branch "$ORIGIN/$BRANCH"
# create tracking branch
- git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
+ git checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
echo
echo "Summary of actions:"
@@ -445,7 +456,7 @@ cmd_checkout() {
if [ "$NAME" != "" ]; then
expand_nameprefix_arg
- git_do checkout "$BRANCH"
+ git checkout "$BRANCH"
else
die "Name a feature branch explicitly."
fi
@@ -464,12 +475,12 @@ cmd_rebase() {
require_clean_working_tree
require_branch "$BRANCH"
- git_do checkout -q "$BRANCH"
+ git checkout -q "$BRANCH"
local OPTS=
if flag interactive; then
OPTS="$OPTS -i"
fi
- git_do rebase $OPTS "$DEVELOP_BRANCH"
+ git rebase $OPTS "$DEVELOP_BRANCH"
}
avoid_accidental_cross_branch_action() {
@@ -511,20 +522,20 @@ cmd_pull() {
# we already have a local branch called like this, so simply pull the
# remote changes in
if flag rebase; then
- if ! git_do pull --rebase -q "$REMOTE" "$BRANCH"; then
+ if ! git pull --rebase -q "$REMOTE" "$BRANCH"; then
warn "Pull was aborted. There might be conflicts during rebase or '$REMOTE' might be inaccessible."
exit 1
fi
else
- git_do pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'."
+ git pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'."
fi
echo "Pulled $REMOTE's changes into $BRANCH."
else
# setup the local branch clone for the first time
- git_do fetch -q "$REMOTE" "$BRANCH" || die "Fetch failed." # stores in FETCH_HEAD
- git_do branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed."
- git_do checkout -q "$BRANCH" || die "Checking out new local branch failed."
+ git fetch -q "$REMOTE" "$BRANCH" || die "Fetch failed." # stores in FETCH_HEAD
+ git branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed."
+ git checkout -q "$BRANCH" || die "Checking out new local branch failed."
echo "Created local branch $BRANCH based on $REMOTE's $BRANCH."
fi
}
View
42 git-flow-init
@@ -53,7 +53,7 @@ cmd_default() {
parse_args "$@"
if ! git rev-parse --git-dir >/dev/null 2>&1; then
- git_do init
+ git init
else
# assure that we are not working in a repo with local changes
git_repo_is_headless || require_clean_working_tree
@@ -121,14 +121,14 @@ cmd_default() {
# name exists, checkout that branch and use it for master
if ! git_local_branch_exists "$master_branch" && \
git_remote_branch_exists "origin/$master_branch"; then
- git_do branch "$master_branch" "origin/$master_branch" >/dev/null 2>&1
+ git branch "$master_branch" "origin/$master_branch" >/dev/null 2>&1
elif ! git_local_branch_exists "$master_branch"; then
die "Local branch '$master_branch' does not exist."
fi
fi
# store the name of the master branch
- git_do config gitflow.branch.master "$master_branch"
+ git config gitflow.branch.master "$master_branch"
fi
# add a develop branch if no such branch exists yet
@@ -185,7 +185,7 @@ cmd_default() {
fi
# store the name of the develop branch
- git_do config gitflow.branch.develop "$develop_branch"
+ git config gitflow.branch.develop "$develop_branch"
fi
# Creation of HEAD
@@ -194,8 +194,8 @@ cmd_default() {
# it to be able to create new branches.
local created_gitflow_branch=0
if ! git rev-parse --quiet --verify HEAD >/dev/null 2>&1; then
- git_do symbolic-ref HEAD "refs/heads/$master_branch"
- git_do commit --allow-empty --quiet -m "Initial commit"
+ git symbolic-ref HEAD "refs/heads/$master_branch"
+ git commit --allow-empty --quiet -m "Initial commit"
created_gitflow_branch=1
fi
@@ -213,9 +213,9 @@ cmd_default() {
# the develop branch now in that case (we base it on master, of course)
if ! git_local_branch_exists "$develop_branch"; then
if git_remote_branch_exists "origin/$develop_branch"; then
- git_do branch "$develop_branch" "origin/$develop_branch" >/dev/null 2>&1
+ git branch "$develop_branch" "origin/$develop_branch" >/dev/null 2>&1
else
- git_do branch --no-track "$develop_branch" "$master_branch"
+ git branch --no-track "$develop_branch" "$master_branch"
fi
created_gitflow_branch=1
fi
@@ -225,7 +225,7 @@ cmd_default() {
# switch to develop branch if its newly created
if [ $created_gitflow_branch -eq 1 ]; then
- git_do checkout -q "$develop_branch"
+ git checkout -q "$develop_branch"
fi
# finally, ask the user for naming conventions (branch and tag prefixes)
@@ -234,6 +234,7 @@ cmd_default() {
! git config --get gitflow.prefix.release >/dev/null 2>&1 ||
! git config --get gitflow.prefix.hotfix >/dev/null 2>&1 ||
! git config --get gitflow.prefix.support >/dev/null 2>&1 ||
+ ! git config --get gitflow.prefix.project >/dev/null 2>&1 ||
! git config --get gitflow.prefix.versiontag >/dev/null 2>&1; then
echo
echo "How to name your supporting branch prefixes?"
@@ -241,6 +242,19 @@ cmd_default() {
local prefix
+ # Project branches
+ if ! git config --get gitflow.prefix.project >/dev/null 2>&1 || flag force; then
+ default_suggestion=$(git config --get gitflow.prefix.project || echo project/)
+ printf "Project branches? [$default_suggestion] "
+ if noflag defaults; then
+ read answer
+ else
+ printf "\n"
+ fi
+ [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
+ git config gitflow.prefix.project "$prefix"
+ fi
+
# Feature branches
if ! git config --get gitflow.prefix.feature >/dev/null 2>&1 || flag force; then
default_suggestion=$(git config --get gitflow.prefix.feature || echo feature/)
@@ -251,7 +265,7 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
- git_do config gitflow.prefix.feature "$prefix"
+ git config gitflow.prefix.feature "$prefix"
fi
# Release branches
@@ -264,7 +278,7 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
- git_do config gitflow.prefix.release "$prefix"
+ git config gitflow.prefix.release "$prefix"
fi
@@ -278,7 +292,7 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
- git_do config gitflow.prefix.hotfix "$prefix"
+ git config gitflow.prefix.hotfix "$prefix"
fi
@@ -292,7 +306,7 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
- git_do config gitflow.prefix.support "$prefix"
+ git config gitflow.prefix.support "$prefix"
fi
@@ -306,7 +320,7 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
- git_do config gitflow.prefix.versiontag "$prefix"
+ git config gitflow.prefix.versiontag "$prefix"
fi
View
530 git-flow-project
@@ -0,0 +1,530 @@
+#
+# git-flow -- A collection of Git extensions to provide high-level
+# repository operations for Vincent Driessen's branching model.
+#
+# Original blog post presenting this model is found at:
+# http://nvie.com/git-model
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright 2010 Vincent Driessen. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and documentation are
+# those of the authors and should not be interpreted as representing official
+# policies, either expressed or implied, of Vincent Driessen.
+#
+
+init() {
+ require_git_repo
+ require_gitflow_initialized
+ gitflow_load_settings
+ PREFIX=$(git config --get gitflow.prefix.project)
+}
+
+usage() {
+ echo "usage: git flow project [list] [-v]"
+ echo " git flow project start [-F] <name> [<base>]"
+ echo " git flow project finish [-rFkDS] [<name|nameprefix>]"
+ echo " git flow project publish <name>"
+ echo " git flow project track <name>"
+ echo " git flow project diff [<name|nameprefix>]"
+ echo " git flow project rebase [-i] [<name|nameprefix>]"
+ echo " git flow project checkout [<name|nameprefix>]"
+ echo " git flow project pull [-r] <remote> [<name>]"
+}
+
+cmd_default() {
+ cmd_list "$@"
+}
+
+cmd_list() {
+ DEFINE_boolean verbose false 'verbose (more) output' v
+ parse_args "$@"
+
+ local project_branches
+ local current_branch
+ local short_names
+ project_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ if [ -z "$project_branches" ]; then
+ warn "No project branches exist."
+ warn ""
+ warn "You can start a new project branch:"
+ warn ""
+ warn " git flow project start <name> [<base>]"
+ warn ""
+ exit 0
+ fi
+ current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
+ short_names=$(echo "$project_branches" | sed "s ^$PREFIX g")
+
+ # determine column width first
+ local width=0
+ local branch
+ for branch in $short_names; do
+ local len=${#branch}
+ width=$(max $width $len)
+ done
+ width=$(($width+3))
+
+ local branch
+ for branch in $short_names; do
+ local fullname=$PREFIX$branch
+ local base=$(git merge-base "$fullname" "$DEVELOP_BRANCH")
+ local develop_sha=$(git rev-parse "$DEVELOP_BRANCH")
+ local branch_sha=$(git rev-parse "$fullname")
+ if [ "$fullname" = "$current_branch" ]; then
+ printf "* "
+ else
+ printf " "
+ fi
+ if flag verbose; then
+ printf "%-${width}s" "$branch"
+ if [ "$branch_sha" = "$develop_sha" ]; then
+ printf "(no commits yet)"
+ elif [ "$base" = "$branch_sha" ]; then
+ printf "(is behind develop, may ff)"
+ elif [ "$base" = "$develop_sha" ]; then
+ printf "(based on latest develop)"
+ else
+ printf "(may be rebased)"
+ fi
+ else
+ printf "%s" "$branch"
+ fi
+ echo
+ done
+}
+
+cmd_help() {
+ usage
+ exit 0
+}
+
+require_name_arg() {
+ if [ "$NAME" = "" ]; then
+ warn "Missing argument <name>"
+ usage
+ exit 1
+ fi
+}
+
+expand_nameprefix_arg() {
+ require_name_arg
+
+ local expanded_name
+ local exitcode
+ expanded_name=$(gitflow_resolve_nameprefix "$NAME" "$PREFIX")
+ exitcode=$?
+ case $exitcode in
+ 0) NAME=$expanded_name
+ BRANCH=$PREFIX$NAME
+ ;;
+ *) exit 1 ;;
+ esac
+}
+
+use_current_project_branch_name() {
+ local current_branch=$(git_current_branch)
+ if startswith "$current_branch" "$PREFIX"; then
+ BRANCH=$current_branch
+ NAME=${BRANCH#$PREFIX}
+ else
+ warn "The current HEAD is no project branch."
+ warn "Please specify a <name> argument."
+ exit 1
+ fi
+}
+
+expand_nameprefix_arg_or_current() {
+ if [ "$NAME" != "" ]; then
+ expand_nameprefix_arg
+ require_branch "$PREFIX$NAME"
+ else
+ use_current_project_branch_name
+ fi
+}
+
+name_or_current() {
+ if [ -z "$NAME" ]; then
+ use_current_project_branch_name
+ fi
+}
+
+parse_args() {
+ # parse options
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+
+ # read arguments into global variables
+ NAME=$1
+ BRANCH=$PREFIX$NAME
+}
+
+parse_remote_name() {
+ # parse options
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+
+ # read arguments into global variables
+ REMOTE=$1
+ NAME=$2
+ BRANCH=$PREFIX$NAME
+}
+
+cmd_start() {
+ DEFINE_boolean fetch false 'fetch from origin before performing local operation' F
+ parse_args "$@"
+ BASE=${2:-$DEVELOP_BRANCH}
+ require_name_arg
+
+ # sanity checks
+ require_branch_absent "$BRANCH"
+
+ # update the local repo with remote changes, if asked
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
+ fi
+
+ # if the origin branch counterpart exists, assert that the local branch
+ # isn't behind it (to avoid unnecessary rebasing)
+ if git_branch_exists "$ORIGIN/$DEVELOP_BRANCH"; then
+ require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+ fi
+
+ # create branch
+ if ! git checkout -b "$BRANCH" "$BASE"; then
+ die "Could not create project branch '$BRANCH'"
+ fi
+
+ echo
+ echo "Summary of actions:"
+ echo "- A new branch '$BRANCH' was created, based on '$BASE'"
+ echo "- You are now on branch '$BRANCH'"
+ echo ""
+ echo "Now, use this project branch as a base for creating feature branches. When the project is done, use:"
+ echo ""
+ echo " git flow project finish $NAME"
+ echo
+}
+
+cmd_finish() {
+ DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
+ DEFINE_boolean rebase false "rebase instead of merge" r
+ DEFINE_boolean keep false "keep branch after performing finish" k
+ DEFINE_boolean force_delete false "force delete project branch after finish" D
+ DEFINE_boolean squash false "squash project during merge" S
+ parse_args "$@"
+ expand_nameprefix_arg_or_current
+
+ # sanity checks
+ require_branch "$BRANCH"
+
+ # detect if we're restoring from a merge conflict
+ if [ -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE" ]; then
+ #
+ # TODO: detect that we're working on the correct branch here!
+ # The user need not necessarily have given the same $NAME twice here
+ # (although he/she should).
+ #
+
+ # TODO: git_is_clean_working_tree() should provide an alternative
+ # exit code for "unmerged changes in working tree", which we should
+ # actually be testing for here
+ if git_is_clean_working_tree; then
+ FINISH_BASE=$(cat "$DOT_GIT_DIR/.gitflow/MERGE_BASE")
+
+ # Since the working tree is now clean, either the user did a
+ # succesfull merge manually, or the merge was cancelled.
+ # We detect this using git_is_branch_merged_into()
+ if git_is_branch_merged_into "$BRANCH" "$FINISH_BASE"; then
+ rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
+ helper_finish_cleanup
+ exit 0
+ else
+ # If the user cancelled the merge and decided to wait until later,
+ # that's fine. But we have to acknowledge this by removing the
+ # MERGE_BASE file and continuing normal execution of the finish
+ rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
+ fi
+ else
+ echo
+ echo "Merge conflicts not resolved yet, use:"
+ echo " git mergetool"
+ echo " git commit"
+ echo
+ echo "You can then complete the finish by running it again:"
+ echo " git flow project finish $NAME"
+ echo
+ exit 1
+ fi
+ fi
+
+ # sanity checks
+ require_clean_working_tree
+
+ # update local repo with remote changes first, if asked
+ if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$BRANCH"
+ git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
+ fi
+ fi
+
+ if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
+ require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
+ fi
+ if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
+ require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+ fi
+
+ # if the user wants to rebase, do that first
+ if flag rebase; then
+ if ! git flow project rebase "$NAME" "$DEVELOP_BRANCH"; then
+ warn "Finish was aborted due to conflicts during rebase."
+ warn "Please finish the rebase manually now."
+ warn "When finished, re-run:"
+ warn " git flow project finish '$NAME' '$DEVELOP_BRANCH'"
+ exit 1
+ fi
+ fi
+
+ # merge into BASE
+ git checkout "$DEVELOP_BRANCH"
+ if [ "$(git rev-list -n2 "$DEVELOP_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then
+ git merge --ff "$BRANCH"
+ else
+ if noflag squash; then
+ git merge --no-ff "$BRANCH"
+ else
+ git merge --squash "$BRANCH"
+ git commit
+ git merge "$BRANCH"
+ fi
+ fi
+
+ if [ $? -ne 0 ]; then
+ # oops.. we have a merge conflict!
+ # write the given $DEVELOP_BRANCH to a temporary file (we need it later)
+ mkdir -p "$DOT_GIT_DIR/.gitflow"
+ echo "$DEVELOP_BRANCH" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
+ echo
+ echo "There were merge conflicts. To resolve the merge conflict manually, use:"
+ echo " git mergetool"
+ echo " git commit"
+ echo
+ echo "You can then complete the finish by running it again:"
+ echo " git flow project finish $NAME"
+ echo
+ exit 1
+ fi
+
+ # when no merge conflict is detected, just clean up the project branch
+ helper_finish_cleanup
+}
+
+helper_finish_cleanup() {
+ # sanity checks
+ require_branch "$BRANCH"
+ require_clean_working_tree
+
+ # delete branch
+ if flag fetch; then
+ git push "$ORIGIN" ":refs/heads/$BRANCH"
+ fi
+
+
+ if noflag keep; then
+ if flag force_delete; then
+ git branch -D "$BRANCH"
+ else
+ git branch -d "$BRANCH"
+ fi
+ fi
+
+ echo
+ echo "Summary of actions:"
+ echo "- The project branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
+ #echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported
+ if flag keep; then
+ echo "- Project branch '$BRANCH' is still available"
+ else
+ echo "- Project branch '$BRANCH' has been removed"
+ fi
+ echo "- You are now on branch '$DEVELOP_BRANCH'"
+ echo
+}
+
+cmd_publish() {
+ parse_args "$@"
+ expand_nameprefix_arg
+
+ # sanity checks
+ require_clean_working_tree
+ require_branch "$BRANCH"
+ git fetch -q "$ORIGIN"
+ require_branch_absent "$ORIGIN/$BRANCH"
+
+ # create remote branch
+ git push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
+ git fetch -q "$ORIGIN"
+
+ # configure remote tracking
+ git config "branch.$BRANCH.remote" "$ORIGIN"
+ git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
+ git checkout "$BRANCH"
+
+ echo
+ echo "Summary of actions:"
+ echo "- A new remote branch '$BRANCH' was created"
+ echo "- The local branch '$BRANCH' was configured to track the remote branch"
+ echo "- You are now on branch '$BRANCH'"
+ echo
+}
+
+cmd_track() {
+ parse_args "$@"
+ require_name_arg
+
+ # sanity checks
+ require_clean_working_tree
+ require_branch_absent "$BRANCH"
+ git fetch -q "$ORIGIN"
+ require_branch "$ORIGIN/$BRANCH"
+
+ # create tracking branch
+ git checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
+
+ echo
+ echo "Summary of actions:"
+ echo "- A new remote tracking branch '$BRANCH' was created"
+ echo "- You are now on branch '$BRANCH'"
+ echo
+}
+
+cmd_diff() {
+ parse_args "$@"
+
+ if [ "$NAME" != "" ]; then
+ expand_nameprefix_arg
+ BASE=$(git merge-base "$DEVELOP_BRANCH" "$BRANCH")
+ git diff "$BASE..$BRANCH"
+ else
+ if ! git_current_branch | grep -q "^$PREFIX"; then
+ die "Not on a project branch. Name one explicitly."
+ fi
+
+ BASE=$(git merge-base "$DEVELOP_BRANCH" HEAD)
+ git diff "$BASE"
+ fi
+}
+
+cmd_checkout() {
+ parse_args "$@"
+
+ if [ "$NAME" != "" ]; then
+ expand_nameprefix_arg
+ git checkout "$BRANCH"
+ else
+ die "Name a project branch explicitly."
+ fi
+}
+
+cmd_co() {
+ # Alias for checkout
+ cmd_checkout "$@"
+}
+
+cmd_rebase() {
+ DEFINE_boolean interactive false 'do an interactive rebase' i
+ parse_args "$@"
+ expand_nameprefix_arg_or_current
+ warn "Will try to rebase '$NAME'..."
+ require_clean_working_tree
+ require_branch "$BRANCH"
+
+ git checkout -q "$BRANCH"
+ local OPTS=
+ if flag interactive; then
+ OPTS="$OPTS -i"
+ fi
+ git rebase $OPTS "$DEVELOP_BRANCH"
+}
+
+avoid_accidental_cross_branch_action() {
+ local current_branch=$(git_current_branch)
+ if [ "$BRANCH" != "$current_branch" ]; then
+ warn "Trying to pull from '$BRANCH' while currently on branch '$current_branch'."
+ warn "To avoid unintended merges, git-flow aborted."
+ return 1
+ fi
+ return 0
+}
+
+cmd_pull() {
+ #DEFINE_string prefix false 'alternative remote project branch name prefix' p
+ DEFINE_boolean rebase false "pull with rebase" r
+ parse_remote_name "$@"
+
+ if [ -z "$REMOTE" ]; then
+ die "Name a remote explicitly."
+ fi
+ name_or_current
+
+ # To avoid accidentally merging different project branches into each other,
+ # die if the current porject branch differs from the requested $NAME
+ # argument.
+ local current_branch=$(git_current_branch)
+ if startswith "$current_branch" "$PREFIX"; then
+ # we are on a local project branch already, so $BRANCH must be equal to
+ # the current branch
+ avoid_accidental_cross_branch_action || die
+ fi
+
+ require_clean_working_tree
+
+ if git_branch_exists "$BRANCH"; then
+ # Again, avoid accidental merges
+ avoid_accidental_cross_branch_action || die
+
+ # we already have a local branch called like this, so simply pull the
+ # remote changes in
+ if flag rebase; then
+ if ! git pull --rebase -q "$REMOTE" "$BRANCH"; then
+ warn "Pull was aborted. There might be conflicts during rebase or '$REMOTE' might be inaccessible."
+ exit 1
+ fi
+ else
+ git pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'."
+ fi
+
+ echo "Pulled $REMOTE's changes into $BRANCH."
+ else
+ # setup the local branch clone for the first time
+ git fetch -q "$REMOTE" "$BRANCH" || die "Fetch failed." # stores in FETCH_HEAD
+ git branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed."
+ git checkout -q "$BRANCH" || die "Checking out new local branch failed."
+ echo "Created local branch $BRANCH based on $REMOTE's $BRANCH."
+ fi
+}
Something went wrong with that request. Please try again.