Merge branch 'release/0.2'
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..8566567
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "shFlags"]
+ path = shFlags
+ url = git://github.com/nvie/shFlags.git
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..11bf22d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+AUTO_DETECTED_GIT_EXEC_PATH := $(shell git --exec-path 2>/dev/null || echo /usr/libexec/git-core)
+GIT_EXEC_PATH=$(AUTO_DETECTED_GIT_EXEC_PATH)
+
+# files that need mode 755
+EXEC_FILES=git-flow
+
+# files that need mode 644
+SCRIPT_FILES =git-flow-init
+SCRIPT_FILES+=git-flow-feature
+SCRIPT_FILES+=git-flow-hotfix
+SCRIPT_FILES+=git-flow-release
+SCRIPT_FILES+=git-flow-support
+SCRIPT_FILES+=git-flow-version
+SCRIPT_FILES+=gitflow-common
+SCRIPT_FILES+=gitflow-shFlags
+
+all:
+ @echo "usage: make install"
+ @echo " make uninstall"
+
+install:
+ @test -f gitflow-shFlags || (echo "Run 'git submodule init && git submodule update' first." ; exit 1 )
+ install -d -m 0755 $(GIT_EXEC_PATH)
+ install -m 0755 $(EXEC_FILES) $(GIT_EXEC_PATH)
+ install -m 0644 $(SCRIPT_FILES) $(GIT_EXEC_PATH)
+
+uninstall:
+ test -d $(GIT_EXEC_PATH) && \
+ cd $(GIT_EXEC_PATH) && \
+ rm -f $(EXEC_FILES) $(SCRIPT_FILES)
diff --git a/README.mdown b/README.mdown
index 86635b6..ed5be33 100644
--- a/README.mdown
+++ b/README.mdown
@@ -1,84 +1,95 @@
-gitflow
-=======
-A collection of Git wrapper scripts to provide high-level repository operations
-for Vincent Driessen's [branching model](http://nvie.com/archives/323 "original
+git-flow
+========
+A collection of Git extensions to provide high-level repository operations
+for Vincent Driessen's [branching model](http://nvie.com/git-model "original
blog post").
-Release 0.1
------------
-A quick release of version 0.1 has arrived. The main script are functional and
-should be usable under "normal" use.
-
-There have barely been any real-world tests, but I encourage you to start using
-it actively. [Feedback](http://github.com/nvie/gitflow/issues) is also very
-welcome. See the "Please help out" section below, also.
-
-**Make sure to validate the modifications to your repo after running any of the
-`gitflow` commands, before pushing them permanently.**
+> **IMPORTANT NOTE:**
+> In release 0.2, the order of the arguments has changed to provide a logical
+> subcommand hierarchy.
-Installing gitflow
-------------------
-There isn't a real Unix installer available, but the project is so small that
-installing it is easy.
+Installing git-flow
+-------------------
+After downloading the sources from Github, also fetch the submodules:
-Either:
+ $ git submodule init
+ $ git submodule update
-- Put the `gitflow` directory anywhere on your Unix `PATH` variable; or
-- Run:
-
- $ git clone git://github.com/nvie/gitflow
- $ cd gitflow
- $ cp gitflow* /usr/local/bin
+Then, you can install `git-flow`, using:
+
+ $ sudo make install
+
+By default, this will look for the directory where Git is already installed,
+and install the git-flow extension alongside the other Git subcommands. If git
+is not on the system's `PATH`, it tries `/usr/libexec/git-core`. To explicitly
+override this setting in case you have installed Git in another location, use:
+
+ $ sudo make GIT_EXEC_PATH=/your/custom/path install
+
+You rarely need to override this manually, the default 'make install' should do
+fine.
+
+Or simply point your `PATH` environment variable to your git-flow checkout
+directory.
Please help out
---------------
-This project is still under development. What is available today is merely its
-foundation. However, it is functional in its current form and should be usable
-under normal use. (Don't try to create multiple release branches next to each
-other and stuff like that, yet.)
-
-Feedback and suggestions are very welcome and I encourage you to use the
-[Issues list](http://github.com/nvie/gitflow/issues) on Github to provide that
+This project is still under development. Feedback and suggestions are very
+welcome and I encourage you to use the [Issues
+list](http://github.com/nvie/gitflow/issues) on Github to provide that
feedback.
Feel free to fork this repo and to commit your additions.
-Example uses:
--------------
+Typical usage:
+--------------
-* To start a new feature branch, use:
-
- gitflow start feature <name> [<base>]
- gitflow start feature foo-support
-
- `base` is `develop` by default.
+### Initialization
-* To finish this feature and have it merged into `develop`, use:
+To initialize a new repo with the basic branch structure, use:
- gitflow finish feature <name>
- gitflow finish feature foo-support
+ git flow init
-* To start a new release branch for 2.0, based on the 1.1 production release, use:
+This will then interactively prompt you with some questions on which branches
+you would like to use as development and production branches, and how you
+would like your prefixes be named. You may simply press Return on any of
+those questions to accept the (sane) default suggestions.
+
+
+### Creating feature/release/hotfix/support branches
+
+* To list/start/finish feature branches, use:
- gitflow start release <release>
- gitflow start release 2.0
+ git flow feature
+ git flow feature start <name> [<base>]
+ git flow feature finish <name>
-* To finish the release branch (i.e. to make an actual production release), use:
+ For feature branches, the `<base>` arg must be a commit on `develop`.
+
+* To list/start/finish release branches, use:
- gitflow finish release <release>
- gitflow finish release 2.0
+ git flow release
+ git flow release start <release> [<base>]
+ git flow release finish <release>
-* To start a new hotfix branch for 2.1, based on the 2.0 production release, use:
+ For release branches, the `<base>` arg must be a commit on `develop`.
- gitflow start hotfix <release> [<base-release>]
- gitflow start hotfix 2.1 2.0
+* To list/start/finish hotfix branches, use:
-* To finish the hotfix branch, use:
+ git flow hotfix
+ git flow hotfix start <release> [<base>]
+ git flow hotfix finish <release>
- gitflow finish hotfix <release>
- gitflow finish hotfix 2.1
+ For hotfix branches, the `<base>` arg must be a commit on `master`.
+
+* To list/start support branches, use:
+
+ git flow support
+ git flow support start <release> <base>
+
+ For support branches, the `<base>` arg must be a commit on `master`.
diff --git a/TODO.mdown b/TODO.mdown
deleted file mode 100644
index 0bb08db..0000000
--- a/TODO.mdown
+++ /dev/null
@@ -1,15 +0,0 @@
-TODO-list
-=========
-
-General configuration
----------------------
-- Support configurable naming for fixed branch names 'master' and 'develop'
-- Support configurable naming conventions (i.e. name prefixes) for supporting
- branches, instead of fixed 'release-\*' and 'hotfix-\*'
-
-Release branch support
-----------------------
-- Take care of the situation where two release branches live next to each
- other. In that situation, a "finish release" action should merge back changes
- into the other release, not into 'develop'. Or at least warn about it. Or not
- support creating a new release branch if the other isn't finished yet.
diff --git a/bump-version b/bump-version
index 60eac0d..f7494c9 100755
--- a/bump-version
+++ b/bump-version
@@ -8,6 +8,11 @@
exit 1
fi
-echo "GITFLOW_VERSION=$1" > gitflow-version
-git add gitflow-version
-git commit -m "Bumped version number to $1" gitflow-version
+if ! sed 's/^GITFLOW_VERSION=.*$/GITFLOW_VERSION='$1'/g' git-flow-version > .git-flow-version.new; then
+ echo "Could not replace GITFLOW_VERSION variable." >&2
+ exit 2
+fi
+
+mv .git-flow-version.new git-flow-version
+git add git-flow-version
+git commit -m "Bumped version number to $1" git-flow-version
diff --git a/git-flow b/git-flow
new file mode 100755
index 0000000..84adc05
--- /dev/null
+++ b/git-flow
@@ -0,0 +1,88 @@
+#!/bin/sh
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+
+# enable debug mode
+if [ "$DEBUG" = "yes" ]; then
+ set -x
+fi
+
+export GITFLOW_DIR=$(dirname "$0")
+
+usage() {
+ echo "usage: git flow <subcommand>"
+ echo
+ echo "Available subcommands are:"
+ echo " init Initialize a new git repo with support for the branching model."
+ echo " feature Manage your feature branches."
+ echo " release Manage your release branches."
+ echo " hotfix Manage your hotfix branches."
+ echo " support Manage your support branches."
+ echo " version Shows version information."
+ echo
+ echo "Try 'git flow <subcommand> help' for details."
+}
+
+main() {
+ if [ $# -lt 1 ]; then
+ usage
+ exit 1
+ fi
+
+ # load common functionality
+ . "$GITFLOW_DIR/gitflow-common"
+
+ # use the shFlags project to parse the command line arguments
+ . "$GITFLOW_DIR/gitflow-shFlags"
+ FLAGS_PARENT="git flow"
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+
+ # sanity checks
+ SUBCOMMAND="$1"; shift
+
+ if [ ! -e "$GITFLOW_DIR/git-flow-$SUBCOMMAND" ]; then
+ usage
+ exit 1
+ fi
+
+ # run command
+ . "$GITFLOW_DIR/git-flow-$SUBCOMMAND"
+ FLAGS_PARENT="git flow $SUBCOMMAND"
+
+ # test if the first argument is a flag (i.e. starts with '-')
+ # in that case, we interpret this arg as a flag for the default
+ # command
+ SUBACTION="default"
+ if [ "$1" != "" ] && ! echo "$1" | grep -q "^-"; then
+ SUBACTION="$1"; shift
+ fi
+ if ! type "cmd_$SUBACTION" >/dev/null 2>&1; then
+ warn "Unknown subcommand: '$SUBACTION'"
+ usage
+ exit 1
+ fi
+
+ # run the specified action
+ cmd_$SUBACTION "$@"
+}
+
+# helper functions for common reuse
+max() { if [ "$1" -gt "$2" ]; then echo "$1"; else echo "$2"; fi; }
+
+# convenience functions for checking whether flags have been set or not
+flag() { eval FLAG=\$FLAGS_$1; [ $FLAG -eq $FLAGS_TRUE ]; }
+noflag() { eval FLAG=\$FLAGS_$1; [ $FLAG -ne $FLAGS_TRUE ]; }
+
+main "$@"
diff --git a/git-flow-feature b/git-flow-feature
new file mode 100644
index 0000000..d8d4bb7
--- /dev/null
+++ b/git-flow-feature
@@ -0,0 +1,378 @@
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+
+require_git_repo
+require_gitflow_initialized
+gitflow_load_settings
+PREFIX=$(git config --get gitflow.prefix.feature)
+
+usage() {
+ echo "usage: git flow feature [list] [-v]"
+ echo " git flow feature start [-Ff] <name> [<base>]"
+ echo " git flow feature finish [-rF] <name|nameprefix>"
+ echo " git flow feature publish <name>"
+ echo " git flow feature track <name>"
+ echo " git flow feature diff [<name|nameprefix>]"
+ echo " git flow feature rebase [-i] [<name|nameprefix>]"
+}
+
+cmd_default() {
+ cmd_list "$@"
+}
+
+cmd_list() {
+ DEFINE_boolean verbose false 'verbose (more) output' v
+ parse_args "$@"
+
+ local feature_branches
+ local current_branch
+ local short_names
+ feature_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ if [ -z "$feature_branches" ]; then
+ warn "No feature branches exist."
+ exit 0
+ fi
+ current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
+ short_names=$(echo "$feature_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
+}
+
+expand_nameprefix_arg_or_current() {
+ if [ "$NAME" != "" ]; then
+ expand_nameprefix_arg
+ require_branch "$PREFIX$NAME"
+ else
+ 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 feature branch."
+ warn "To diff a feature, specify a <name> argument."
+ usage
+ exit 1
+ fi
+ fi
+}
+
+parse_args() {
+ # parse options
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+
+ # read arguments into global variables
+ NAME=$1
+ BRANCH=$PREFIX$NAME
+}
+
+cmd_start() {
+ DEFINE_boolean fetch false 'fetch from origin before performing local operation' F
+ DEFINE_boolean force false 'force creation of feature branch (ignores dirty working tree)' f
+ parse_args "$@"
+ BASE=${2:-$DEVELOP_BRANCH}
+ require_name_arg
+
+ # sanity checks
+ if noflag force; then
+ require_clean_working_tree
+ fi
+ require_branch_absent "$BRANCH"
+
+ # update the local repo with remote changes, if asked
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
+ fi
+
+ require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+
+ # create branch
+ if ! git checkout -b "$BRANCH" "$BASE"; then
+ die "Could not create feature 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, start committing on your feature. When done, use:"
+ echo ""
+ echo " git flow finish feature $NAME"
+ echo
+}
+
+cmd_finish() {
+ DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
+ DEFINE_boolean rebase false 'rebase instead of merge' r
+ parse_args "$@"
+ expand_nameprefix_arg
+
+ # 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 feature finish $NAME"
+ echo
+ exit 1
+ fi
+ fi
+
+ # sanity checks
+ require_clean_working_tree
+
+ # update local repo with remote changes first, if asked
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$BRANCH"
+ fi
+
+ if has "$ORIGIN/$BRANCH" "$(git_remote_branches)"; then
+ require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
+ fi
+ require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+
+ # if the user wants to rebase, do that first
+ if flag rebase; then
+ if ! git flow feature 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 feature 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
+ git merge --no-ff "$BRANCH"
+ 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 feature finish $NAME"
+ echo
+ exit 1
+ fi
+
+ # when no merge conflict is detected, just clean up the feature 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
+ git branch -d "$BRANCH"
+
+ echo
+ echo "Summary of actions:"
+ echo "- The feature branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
+ #echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported
+ echo "- Feature branch '$BRANCH' has been removed"
+ 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 feature branch. Name one explicitly."
+ fi
+
+ BASE=$(git merge-base "$DEVELOP_BRANCH" HEAD)
+ git diff "$BASE"
+ fi
+}
+
+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"
+}
diff --git a/git-flow-hotfix b/git-flow-hotfix
new file mode 100644
index 0000000..5866178
--- /dev/null
+++ b/git-flow-hotfix
@@ -0,0 +1,247 @@
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+
+require_git_repo
+require_gitflow_initialized
+gitflow_load_settings
+VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
+PREFIX=$(git config --get gitflow.prefix.hotfix)
+
+usage() {
+ echo "usage: git flow hotfix [list] [-v]"
+ echo " git flow hotfix start [-F] <version> [<base>]"
+ echo " git flow hotfix finish [-Fsump] <version>"
+}
+
+cmd_default() {
+ cmd_list "$@"
+}
+
+cmd_list() {
+ DEFINE_boolean verbose false 'verbose (more) output' v
+ parse_args "$@"
+
+ local hotfix_branches
+ local current_branch
+ local short_names
+ hotfix_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ if [ -z "$hotfix_branches" ]; then
+ warn "No hotfix branches exist."
+ exit 0
+ fi
+ current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
+ short_names=$(echo "$hotfix_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" "$MASTER_BRANCH")
+ local master_sha=$(git rev-parse "$MASTER_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" = "$master_sha" ]; then
+ printf "(no commits yet)"
+ else
+ local tagname=$(git name-rev --tags --no-undefined --name-only "$base")
+ local nicename
+ if [ "$tagname" != "" ]; then
+ nicename=$tagname
+ else
+ nicename=$(git rev-parse --short "$base")
+ fi
+ printf "(based on $nicename)"
+ fi
+ else
+ printf "%s" "$branch"
+ fi
+ echo
+ done
+}
+
+cmd_help() {
+ usage
+ exit 0
+}
+
+parse_args() {
+ # parse options
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+
+ # read arguments into global variables
+ VERSION=$1
+ BRANCH=$PREFIX$VERSION
+}
+
+require_version_arg() {
+ if [ "$VERSION" = "" ]; then
+ warn "Missing argument <version>"
+ usage
+ exit 1
+ fi
+}
+
+require_base_is_on_master() {
+ if ! git branch --contains "$BASE" 2>/dev/null \
+ | sed 's/[* ] //g' \
+ | grep -q "^$MASTER_BRANCH\$"; then
+ die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
+ fi
+}
+
+require_no_existing_hotfix_branches() {
+ local hotfix_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ local first_branch=$(echo ${hotfix_branches} | head -n1)
+ first_branch=${first_branch#$PREFIX}
+ [ -z "$hotfix_branches" ] || \
+ die "There is an existing hotfix branch ($first_branch). Finish that one first."
+}
+
+cmd_start() {
+ DEFINE_boolean fetch true "fetch from $ORIGIN before performing finish" F
+ parse_args "$@"
+ BASE=${2:-$MASTER_BRANCH}
+ require_version_arg
+ require_base_is_on_master
+ require_no_existing_hotfix_branches
+
+ # sanity checks
+ require_clean_working_tree
+ require_branch_absent "$BRANCH"
+ require_tag_absent "$VERSION_PREFIX$VERSION"
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$MASTER_BRANCH"
+ fi
+ require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
+
+ # create branch
+ git checkout -b "$BRANCH" "$BASE"
+
+ echo
+ echo "Summary of actions:"
+ echo "- A new branch '$BRANCH' was created, based on '$BASE'"
+ echo "- You are now on branch '$BRANCH'"
+ echo
+ echo "Follow-up actions:"
+ echo "- Bump the version number now!"
+ echo "- Start committing your hot fixes"
+ echo "- When done, run:"
+ echo
+ echo " git flow hotfix finish '$VERSION'"
+ echo
+}
+
+cmd_finish() {
+ DEFINE_boolean fetch true "fetch from $ORIGIN before performing finish" F
+ DEFINE_boolean sign false "sign the release tag cryptographically" s
+ DEFINE_string signingkey "" "use the given GPG-key for the digital signature (implies -s)" u
+ DEFINE_string message "" "use the given tag message" m
+ DEFINE_boolean push false "push to $ORIGIN after performing finish" p
+ parse_args "$@"
+ require_version_arg
+
+ # handle flags that imply other flags
+ if [ "$FLAGS_signingkey" != "" ]; then
+ FLAGS_sign=$FLAGS_TRUE
+ fi
+
+ # sanity checks
+ require_branch "$BRANCH"
+ require_clean_working_tree
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$MASTER_BRANCH" || \
+ die "Could not fetch $MASTER_BRANCH from $ORIGIN."
+ git fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \
+ die "Could not fetch $DEVELOP_BRANCH from $ORIGIN."
+ fi
+ require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
+ require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+
+ # try to merge into master
+ # in case a previous attempt to finish this release branch has failed,
+ # but the merge into master was successful, we skip it now
+ if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then
+ git checkout "$MASTER_BRANCH" || \
+ die "Could not check out $MASTER_BRANCH."
+ git merge --no-ff "$BRANCH" || \
+ die "There were merge conflicts."
+ # TODO: What do we do now?
+ fi
+
+ # try to tag the release
+ # in case a previous attempt to finish this release branch has failed,
+ # but the tag was set successful, we skip it now
+ local tagname=$VERSION_PREFIX$VERSION
+ if ! git_tag_exists "$tagname"; then
+ local opts="-a"
+ flag sign && opts="$opts -s"
+ [ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
+ [ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
+ git tag $opts "$VERSION_PREFIX$VERSION" || \
+ die "Tagging failed. Please run finish again to retry."
+ fi
+
+ # try to merge into develop
+ # in case a previous attempt to finish this release branch has failed,
+ # but the merge into develop was successful, we skip it now
+ if ! git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH"; then
+ git checkout "$DEVELOP_BRANCH" || \
+ die "Could not check out $DEVELOP_BRANCH."
+
+ # TODO: Actually, accounting for 'git describe' pays, so we should
+ # ideally git merge --no-ff $tagname here, instead!
+ git merge --no-ff "$BRANCH" || \
+ die "There were merge conflicts."
+ # TODO: What do we do now?
+ fi
+
+ # delete branch
+ git branch -d "$BRANCH"
+
+ if flag push; then
+ git push "$ORIGIN" "$DEVELOP_BRANCH" || \
+ die "Could not push to $DEVELOP_BRANCH from $ORIGIN."
+ git push "$ORIGIN" "$MASTER_BRANCH" || \
+ die "Could not push to $MASTER_BRANCH from $ORIGIN."
+ git push --tags "$ORIGIN" || \
+ die "Could not push tags to $ORIGIN."
+ fi
+
+ echo
+ echo "Summary of actions:"
+ echo "- Latest objects have been fetched from '$ORIGIN'"
+ echo "- Hotfix branch has been merged into '$MASTER_BRANCH'"
+ echo "- The hotfix was tagged '$VERSION_PREFIX$VERSION'"
+ echo "- Hotfix branch has been back-merged into '$DEVELOP_BRANCH'"
+ echo "- Hotfix branch '$BRANCH' has been deleted"
+ if flag push; then
+ echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
+ fi
+ echo
+}
diff --git a/git-flow-init b/git-flow-init
new file mode 100644
index 0000000..ffc9e96
--- /dev/null
+++ b/git-flow-init
@@ -0,0 +1,237 @@
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+
+usage() {
+ echo "usage: git flow init [-f]"
+}
+
+parse_args() {
+ # parse options
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+}
+
+# Default entry when no SUBACTION is given
+cmd_default() {
+ DEFINE_boolean force false 'force setting of gitflow branches, even if already configured' f
+ parse_args "$@"
+
+ if ! git rev-parse --git-dir >/dev/null 2>&1; then
+ git init
+ else
+ # assure that we are not working in a repo with local changes
+ git_repo_is_headless || require_clean_working_tree
+ fi
+
+ # running git flow init on an already initialized repo is fine
+ if gitflow_is_initialized && ! flag force; then
+ warn "Already initialized for gitflow."
+ warn "To force reinitialization, use: git flow init -f"
+ exit 0
+ fi
+
+ local branch_count
+ local answer
+
+ # add a master branch if no such branch exists yet
+ local master_branch
+ if gitflow_has_master_configured && ! flag force; then
+ master_branch=$(git config --get gitflow.branch.master)
+ else
+ # Two cases are distinguished:
+ # 1. A fresh git repo (without any branches)
+ # We will create a new master/develop branch for the user
+ # 2. Some branches do already exist
+ # We will disallow creation of new master/develop branches and
+ # rather allow to use existing branches for git-flow.
+ local default_suggestion
+ local should_check_existence
+ branch_count=$(git_local_branches | wc -l)
+ if [ "$branch_count" -eq 0 ]; then
+ echo "No branches exist yet. Base branches must be created now."
+ should_check_existence=NO
+ default_suggestion=master
+ else
+ echo
+ echo "Which branch should be used for bringing forth production releases?"
+ git_local_branches | sed 's/^.*$/ - &/g'
+
+ should_check_existence=YES
+ default_suggestion=
+ for guess in 'production' 'main' 'master'; do
+ if git_local_branch_exists "$guess"; then
+ default_suggestion="$guess"
+ break
+ fi
+ done
+ fi
+
+ echo "Branch name for production releases: [$default_suggestion] \c"
+ read answer
+ master_branch=${answer:-$default_suggestion}
+
+ # check existence in case of an already existing repo
+ if [ "$should_check_existence" = "YES" ]; then
+ git_local_branch_exists "$master_branch" || \
+ die "Local branch '$master_branch' does not exist."
+ fi
+
+ # store the name of the master branch
+ git config gitflow.branch.master "$master_branch"
+ fi
+
+ # add a develop branch if no such branch exists yet
+ local develop_branch
+ if gitflow_has_develop_configured && ! flag force; then
+ develop_branch=$(git config --get gitflow.branch.develop)
+ else
+ # Again, the same two cases as with the master selection are
+ # considered (fresh repo or repo that contains branches)
+ local default_suggestion
+ local should_check_existence
+ branch_count=$(git_local_branches | grep -v "^${master_branch}\$" | wc -l)
+ if [ "$branch_count" -eq 0 ]; then
+ should_check_existence=NO
+ default_suggestion=develop
+ else
+ echo
+ echo "Which branch should be used for integration of the \"next release\"?"
+ git_local_branches | grep -v "^${master_branch}\$" | sed 's/^.*$/ - &/g'
+
+ should_check_existence=YES
+ default_suggestion=
+ for guess in 'develop' 'int' 'integration' 'master'; do
+ if git_local_branch_exists "$guess"; then
+ default_suggestion="$guess"
+ break
+ fi
+ done
+ fi
+
+ echo "Branch name for \"next release\" development: [$default_suggestion] \c"
+ read answer
+ develop_branch=${answer:-$default_suggestion}
+
+ if [ "$master_branch" = "$develop_branch" ]; then
+ die "Production and integration branches should differ."
+ fi
+
+ # check existence in case of an already existing repo
+ if [ "$should_check_existence" = "YES" ]; then
+ git_local_branch_exists "$develop_branch" || \
+ die "Local branch '$develop_branch' does not exist."
+ fi
+
+ # store the name of the develop branch
+ git config gitflow.branch.develop "$develop_branch"
+ fi
+
+ # Creation of HEAD
+ # ----------------
+ # We create a HEAD now, if it does not exist yet (in a fresh repo). We need
+ # 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 symbolic-ref HEAD "refs/heads/$master_branch"
+ git commit --allow-empty --quiet -m "Initial commit"
+ created_gitflow_branch=1
+ fi
+
+ # Creation of master
+ # ------------------
+ # At this point, there always is a master branch: either it existed already
+ # (and was picked interactively as the production branch) or it has just
+ # been created in a fresh repo
+
+ # Creation of develop
+ # -------------------
+ # The develop branch possibly does not exist yet. This is the case when,
+ # in a git init'ed repo with one or more commits, master was picked as the
+ # default production branch and develop was "created". We should create
+ # the develop branch now in that case (we base it on master, of course)
+ if ! git_local_branch_exists "$develop_branch"; then
+ git branch "$develop_branch" "$master_branch"
+ created_gitflow_branch=1
+ fi
+
+ # assert the gitflow repo has been correctly initialized
+ gitflow_is_initialized
+
+ # switch to develop branch if its newly created
+ if [ $created_gitflow_branch -eq 1 ]; then
+ git checkout -q "$develop_branch"
+ fi
+
+ # finally, ask the user for naming conventions (branch and tag prefixes)
+ echo
+ echo "How to name your supporting branch prefixes?"
+
+ local prefix
+
+ # 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/)
+ echo "Feature branches? [$default_suggestion] \c"
+ read answer
+ [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
+ git config gitflow.prefix.feature "$prefix"
+ fi
+
+ # Release branches
+ if ! git config --get gitflow.prefix.release >/dev/null 2>&1 || flag force; then
+ default_suggestion=$(git config --get gitflow.prefix.release || echo release/)
+ echo "Release branches? [$default_suggestion] \c"
+ read answer
+ [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
+ git config gitflow.prefix.release "$prefix"
+ fi
+
+
+ # Hotfix branches
+ if ! git config --get gitflow.prefix.hotfix >/dev/null 2>&1 || flag force; then
+ default_suggestion=$(git config --get gitflow.prefix.hotfix || echo hotfix/)
+ echo "Hotfix branches? [$default_suggestion] \c"
+ read answer
+ [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
+ git config gitflow.prefix.hotfix "$prefix"
+ fi
+
+
+ # Support branches
+ if ! git config --get gitflow.prefix.support >/dev/null 2>&1 || flag force; then
+ default_suggestion=$(git config --get gitflow.prefix.support || echo support/)
+ echo "Support branches? [$default_suggestion] \c"
+ read answer
+ [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
+ git config gitflow.prefix.support "$prefix"
+ fi
+
+
+ # Version tag prefix
+ if ! git config --get gitflow.prefix.versiontag >/dev/null 2>&1 || flag force; then
+ default_suggestion=$(git config --get gitflow.prefix.versiontag || echo "")
+ echo "Version tag prefix? [$default_suggestion] \c"
+ read answer
+ [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
+ git config gitflow.prefix.versiontag "$prefix"
+ fi
+
+
+ # TODO: what to do with origin?
+}
+
+cmd_help() {
+ usage
+ exit 0
+}
diff --git a/git-flow-release b/git-flow-release
new file mode 100644
index 0000000..2a46a7a
--- /dev/null
+++ b/git-flow-release
@@ -0,0 +1,243 @@
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+
+require_git_repo
+require_gitflow_initialized
+gitflow_load_settings
+VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
+PREFIX=$(git config --get gitflow.prefix.release)
+
+usage() {
+ echo "usage: git flow release [list] [-v]"
+ echo " git flow release start [-F] <version>"
+ echo " git flow release finish [-Fsump] <version>"
+}
+
+cmd_default() {
+ cmd_list "$@"
+}
+
+cmd_list() {
+ DEFINE_boolean verbose false 'verbose (more) output' v
+ parse_args "$@"
+
+ local release_branches
+ local current_branch
+ local short_names
+ release_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ if [ -z "$release_branches" ]; then
+ warn "No release branches exist."
+ exit 0
+ fi
+
+ current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
+ short_names=$(echo "$release_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)"
+ else
+ local nicename=$(git rev-parse --short "$base")
+ printf "(based on $nicename)"
+ fi
+ else
+ printf "%s" "$branch"
+ fi
+ echo
+ done
+}
+
+cmd_help() {
+ usage
+ exit 0
+}
+
+parse_args() {
+ # parse options
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+
+ # read arguments into global variables
+ VERSION=$1
+ BRANCH=$PREFIX$VERSION
+}
+
+require_version_arg() {
+ if [ "$VERSION" = "" ]; then
+ warn "Missing argument <version>"
+ usage
+ exit 1
+ fi
+}
+
+require_base_is_on_develop() {
+ if ! git branch --contains "$BASE" 2>/dev/null \
+ | sed 's/[* ] //g' \
+ | grep -q "^$DEVELOP_BRANCH\$"; then
+ die "fatal: Given base '$BASE' is not a valid commit on '$DEVELOP_BRANCH'."
+ fi
+}
+
+require_no_existing_release_branches() {
+ local release_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ local first_branch=$(echo ${release_branches} | head -n1)
+ first_branch=${first_branch#$PREFIX}
+ [ -z "$release_branches" ] || \
+ die "There is an existing release branch ($first_branch). Finish that one first."
+}
+
+cmd_start() {
+ DEFINE_boolean fetch true "fetch from $ORIGIN before performing finish" F
+ parse_args "$@"
+ BASE=${2:-$DEVELOP_BRANCH}
+ require_version_arg
+ require_base_is_on_develop
+ require_no_existing_release_branches
+
+ # sanity checks
+ require_clean_working_tree
+ require_branch_absent "$BRANCH"
+ require_tag_absent "$VERSION_PREFIX$VERSION"
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
+ fi
+ require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+
+ # create branch
+ git checkout -b "$BRANCH" "$BASE"
+
+ echo
+ echo "Summary of actions:"
+ echo "- A new branch '$BRANCH' was created, based on '$BASE'"
+ echo "- You are now on branch '$BRANCH'"
+ echo
+ echo "Follow-up actions:"
+ echo "- Bump the version number now!"
+ echo "- Start committing last-minute fixes in preparing your release"
+ echo "- When done, run:"
+ echo
+ echo " git flow release finish '$VERSION'"
+ echo
+}
+
+cmd_finish() {
+ DEFINE_boolean fetch true "fetch from $ORIGIN before performing finish" F
+ DEFINE_boolean sign false "sign the release tag cryptographically" s
+ DEFINE_string signingkey "" "use the given GPG-key for the digital signature (implies -s)" u
+ DEFINE_string message "" "use the given tag message" m
+ DEFINE_boolean push false "push to $ORIGIN after performing finish" p
+
+ parse_args "$@"
+ require_version_arg
+
+ # handle flags that imply other flags
+ if [ "$FLAGS_signingkey" != "" ]; then
+ FLAGS_sign=$FLAGS_TRUE
+ fi
+
+ # sanity checks
+ require_branch "$BRANCH"
+ require_clean_working_tree
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$MASTER_BRANCH" || \
+ die "Could not fetch $MASTER_BRANCH from $ORIGIN."
+ git fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \
+ die "Could not fetch $DEVELOP_BRANCH from $ORIGIN."
+ fi
+ require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
+ require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
+
+ # try to merge into master
+ # in case a previous attempt to finish this release branch has failed,
+ # but the merge into master was successful, we skip it now
+ if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then
+ git checkout "$MASTER_BRANCH" || \
+ die "Could not check out $MASTER_BRANCH."
+ git merge --no-ff "$BRANCH" || \
+ die "There were merge conflicts."
+ # TODO: What do we do now?
+ fi
+
+ # try to tag the release
+ # in case a previous attempt to finish this release branch has failed,
+ # but the tag was set successful, we skip it now
+ local tagname=$VERSION_PREFIX$VERSION
+ if ! git_tag_exists "$tagname"; then
+ local opts="-a"
+ flag sign && opts="$opts -s"
+ [ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
+ [ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
+ git tag $opts "$tagname" || \
+ die "Tagging failed. Please run finish again to retry."
+ fi
+
+ # try to merge into develop
+ # in case a previous attempt to finish this release branch has failed,
+ # but the merge into develop was successful, we skip it now
+ if ! git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH"; then
+ git checkout "$DEVELOP_BRANCH" || \
+ die "Could not check out $DEVELOP_BRANCH."
+
+ # TODO: Actually, accounting for 'git describe' pays, so we should
+ # ideally git merge --no-ff $tagname here, instead!
+ git merge --no-ff "$BRANCH" || \
+ die "There were merge conflicts."
+ # TODO: What do we do now?
+ fi
+
+ # delete branch
+ git branch -d "$BRANCH"
+
+ if flag push; then
+ git push "$ORIGIN" "$DEVELOP_BRANCH" || \
+ die "Could not push to $DEVELOP_BRANCH from $ORIGIN."
+ git push "$ORIGIN" "$MASTER_BRANCH" || \
+ die "Could not push to $MASTER_BRANCH from $ORIGIN."
+ git push --tags "$ORIGIN" || \
+ die "Could not push tags to $ORIGIN."
+ fi
+
+ echo
+ echo "Summary of actions:"
+ echo "- Latest objects have been fetched from '$ORIGIN'"
+ echo "- Release branch has been merged into '$MASTER_BRANCH'"
+ echo "- The release was tagged '$tagname'"
+ echo "- Release branch has been back-merged into '$DEVELOP_BRANCH'"
+ echo "- Release branch '$BRANCH' has been deleted"
+ if flag push; then
+ echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
+ fi
+ echo
+}
diff --git a/git-flow-support b/git-flow-support
new file mode 100644
index 0000000..9403c12
--- /dev/null
+++ b/git-flow-support
@@ -0,0 +1,153 @@
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+
+require_git_repo
+require_gitflow_initialized
+gitflow_load_settings
+VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
+PREFIX=$(git config --get gitflow.prefix.support)
+
+warn "note: The support subcommand is still very EXPERIMENTAL!"
+warn "note: DO NOT use it in a production situation."
+
+usage() {
+ echo "usage: git flow support [list] [-v]"
+ echo " git flow support start [-F] <version> <base>"
+}
+
+cmd_default() {
+ cmd_list "$@"
+}
+
+cmd_list() {
+ DEFINE_boolean verbose false 'verbose (more) output' v
+ parse_args "$@"
+
+ local support_branches
+ local current_branch
+ local short_names
+ support_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ if [ -z "$support_branches" ]; then
+ warn "No support branches exist."
+ exit 0
+ fi
+ current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
+ short_names=$(echo "$support_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" "$MASTER_BRANCH")
+ local master_sha=$(git rev-parse "$MASTER_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" = "$master_sha" ]; then
+ printf "(no commits yet)"
+ else
+ local tagname=$(git name-rev --tags --no-undefined --name-only "$base")
+ local nicename
+ if [ "$tagname" != "" ]; then
+ nicename=$tagname
+ else
+ nicename=$(git rev-parse --short "$base")
+ fi
+ printf "(based on $nicename)"
+ fi
+ else
+ printf "%s" "$branch"
+ fi
+ echo
+ done
+}
+
+cmd_help() {
+ usage
+ exit 0
+}
+
+parse_args() {
+ # parse options
+ FLAGS "$@" || exit $?
+ eval set -- "${FLAGS_ARGV}"
+
+ # read arguments into global variables
+ VERSION=$1
+ BASE=$2
+ BRANCH=$PREFIX$VERSION
+}
+
+require_version_arg() {
+ if [ "$VERSION" = "" ]; then
+ warn "Missing argument <version>"
+ usage
+ exit 1
+ fi
+}
+
+require_base_arg() {
+ if [ "$BASE" = "" ]; then
+ warn "Missing argument <base>"
+ usage
+ exit 1
+ fi
+}
+
+require_base_is_on_master() {
+ if ! git branch --contains "$BASE" 2>/dev/null \
+ | sed 's/[* ] //g' \
+ | grep -q "^$MASTER_BRANCH\$"; then
+ die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
+ fi
+}
+
+cmd_start() {
+ DEFINE_boolean fetch true "fetch from $ORIGIN before performing finish" F
+ parse_args "$@"
+ require_version_arg
+ require_base_arg
+ require_base_is_on_master
+
+ # sanity checks
+ require_clean_working_tree
+
+ # fetch remote changes
+ if flag fetch; then
+ git fetch -q "$ORIGIN" "$BASE"
+ fi
+ require_branch_absent "$BRANCH"
+
+ # create branch
+ git checkout -b "$BRANCH" "$BASE"
+
+ echo
+ echo "Summary of actions:"
+ echo "- A new branch '$BRANCH' was created, based on '$BASE'"
+ echo "- You are now on branch '$BRANCH'"
+ echo
+}
diff --git a/git-flow-version b/git-flow-version
new file mode 100644
index 0000000..cd5bb45
--- /dev/null
+++ b/git-flow-version
@@ -0,0 +1,27 @@
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+GITFLOW_VERSION=0.2
+
+usage() {
+ echo "usage: git flow version"
+}
+
+cmd_default() {
+ echo "$GITFLOW_VERSION"
+}
+
+cmd_help() {
+ usage
+ exit 0
+}
diff --git a/gitflow b/gitflow
deleted file mode 100755
index 28da0af..0000000
--- a/gitflow
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/sh
-#
-# gitflow -- A collection of Git wrapper scripts to provide high-level
-# repository operations for Vincent Driessen's branching model:
-#
-# Original blog post presenting this model is found at:
-# http://nvie.com/archives/323
-#
-# Feel free to contribute to this project at:
-# http://github.com/nvie/gitflow
-#
-# Copyright (c) 2010 by Vincent Driessen
-#
-
-export GITFLOW_DIR=$(dirname "$0")
-
-usage() {
- . "$GITFLOW_DIR/gitflow-version"
- echo "gitflow, version $GITFLOW_VERSION"
- echo ""
- echo "usage: gitflow <start|finish> <type> <args>"
- echo ""
- echo "arguments:"
- echo "type can be any of: \"feature\", \"release\", \"hotfix\""
- echo ""
-}
-
-check_incoming() {
- if [ "$ACTION" != "start" -a "$ACTION" != "finish" ]; then
- usage
- exit 1
- fi
-
- if [ "$BTYPE" != "feature" -a "$BTYPE" != "release" -a "$BTYPE" != "hotfix" ]; then
- usage
- exit 1
- fi
-}
-
-if [ $# -lt 2 ]; then
- usage
- exit 1
-fi
-
-# Set & check arguments
-ACTION="$1"
-BTYPE="$2"
-shift 2
-check_incoming
-
-# Now, $ACTION and $BTYPE are set
-# It's time to call the appropriate subcommand
-. "$GITFLOW_DIR/gitflow-sh-setup"
-. "$GITFLOW_DIR/gitflow-$BTYPE"
-
-if [ "$ACTION" = "start" ]; then
- start "$@"
-elif [ "$ACTION" = "finish" ]; then
- finish "$@"
-else
- usage
-fi
diff --git a/gitflow-common b/gitflow-common
new file mode 100644
index 0000000..aa33700
--- /dev/null
+++ b/gitflow-common
@@ -0,0 +1,284 @@
+#
+# 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/archives/323
+#
+# Feel free to contribute to this project at:
+# http://github.com/nvie/gitflow
+#
+# Copyright (c) 2010 by Vincent Driessen
+# Copyright (c) 2010 by Benedikt Böhm
+#
+
+#
+# Common functionality
+#
+
+# shell output
+warn() { echo "$@" >&2; }
+die() { warn "$@"; exit 1; }
+
+# set logic
+has() {
+ local item=$1; shift
+ echo " $@ " | grep -q " $item "
+}
+
+# basic math
+min() { [ "$1" -le "$2" ] && echo "$1" || echo "$2"; }
+max() { [ "$1" -ge "$2" ] && echo "$1" || echo "$2"; }
+
+# basic string matching
+startswith() { [ "$1" != "${1#$2}" ]; }
+endswith() { [ "$1" != "${1%$2}" ]; }
+
+# convenience functions for checking shFlags flags
+flag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -eq $FLAGS_TRUE ]; }
+noflag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -ne $FLAGS_TRUE ]; }
+
+#
+# Git specific common functionality
+#
+
+git_local_branches() { git branch | sed 's/^[* ] //'; }
+git_remote_branches() { git branch -r | sed 's/^[* ] //'; }
+git_all_branches() { ( git branch; git branch -r) | sed 's/^[* ] //'; }
+git_all_tags() { git tag; }
+
+git_current_branch() {
+ git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'
+}
+
+git_is_clean_working_tree() {
+ if ! git diff --no-ext-diff --ignore-submodules --quiet --exit-code; then
+ return 1
+ elif ! git diff-index --cached --quiet --ignore-submodules HEAD --; then
+ return 2
+ else
+ return 0
+ fi
+}
+
+git_repo_is_headless() {
+ ! git rev-parse --quiet --verify HEAD >/dev/null 2>&1
+}
+
+git_local_branch_exists() {
+ has $1 $(git_local_branches)
+}
+
+git_branch_exists() {
+ has $1 $(git_all_branches)
+}
+
+git_tag_exists() {
+ has $1 $(git_all_tags)
+}
+
+#
+# git_compare_branches()
+#
+# Tests whether branches and their "origin" counterparts have diverged and need
+# merging first. It returns error codes to provide more detail, like so:
+#
+# 0 Branch heads point to the same commit
+# 1 First given branch needs fast-forwarding
+# 2 Second given branch needs fast-forwarding
+# 3 Branch needs a real merge
+# 4 There is no merge base, i.e. the branches have no common ancestors
+#
+git_compare_branches() {
+ local commit1=$(git rev-parse "$1")
+ local commit2=$(git rev-parse "$2")
+ if [ "$commit1" != "$commit2" ]; then
+ local base=$(git merge-base "$commit1" "$commit2")
+ if [ $? -ne 0 ]; then
+ return 4
+ elif [ "$commit1" = "$base" ]; then
+ return 1
+ elif [ "$commit2" = "$base" ]; then
+ return 2
+ else
+ return 3
+ fi
+ else
+ return 0
+ fi
+}
+
+#
+# git_is_branch_merged_into()
+#
+# Checks whether branch $1 is succesfully merged into $2
+#
+git_is_branch_merged_into() {
+ local subject=$1
+ local base=$2
+ local all_merges=$(git branch --contains $subject | sed 's/^[* ] //')
+ has $base $all_merges
+}
+
+#
+# gitflow specific common functionality
+#
+
+# check if this repo has been inited for gitflow
+gitflow_has_master_configured() {
+ local master=$(git config --get gitflow.branch.master)
+ [ "$master" != "" ] && git_local_branch_exists "$master"
+}
+
+gitflow_has_develop_configured() {
+ local develop=$(git config --get gitflow.branch.develop)
+ [ "$develop" != "" ] && git_local_branch_exists "$develop"
+}
+
+gitflow_has_prefixes_configured() {
+ git config --get gitflow.prefix.feature >/dev/null 2>&1 && \
+ 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.versiontag >/dev/null 2>&1
+}
+
+gitflow_is_initialized() {
+ gitflow_has_master_configured && \
+ gitflow_has_develop_configured && \
+ [ "$(git config --get gitflow.branch.master)" != \
+ "$(git config --get gitflow.branch.develop)" ] && \
+ gitflow_has_prefixes_configured
+}
+
+# loading settings that can be overridden using git config
+gitflow_load_settings() {
+ export DOT_GIT_DIR=$(git rev-parse --git-dir >/dev/null 2>&1)
+ export MASTER_BRANCH=$(git config --get gitflow.branch.master)
+ export DEVELOP_BRANCH=$(git config --get gitflow.branch.develop)
+ export ORIGIN=$(git config --get gitflow.origin || echo origin)
+}
+
+#
+# gitflow_resolve_nameprefix
+#
+# Inputs:
+# $1 = name prefix to resolve
+# $2 = branch prefix to use
+#
+# Searches branch names from git_local_branches() to look for a unique
+# branch name whose name starts with the given name prefix.
+#
+# There are multiple exit codes possible:
+# 0: The unambiguous full name of the branch is written to stdout
+# (success)
+# 1: No match is found.
+# 2: Multiple matches found. These matches are written to stderr
+#
+gitflow_resolve_nameprefix() {
+ local name=$1
+ local prefix=$2
+ local matches
+ local num_matches
+
+ # first, check if there is a perfect match
+ if has "$(git_local_branches)" "$prefix$name"; then
+ echo "$name"
+ return 0
+ fi
+
+ matches=$(echo "$(git_local_branches)" | grep "^$prefix$name")
+ num_matches=$(echo "$matches" | wc -l)
+ if [ -z "$matches" ]; then
+ # no prefix match, so take it literally
+ warn "No branch matches prefix '$name'"
+ return 1
+ else
+ if [ $num_matches -eq 1 ]; then
+ echo "${matches#$prefix}"
+ return 0
+ else
+ # multiple matches, cannot decide
+ warn "Multiple branches match prefix '$name':"
+ for match in $matches; do
+ warn "- $match"
+ done
+ return 2
+ fi
+ fi
+}
+
+#
+# Assertions for use in git-flow subcommands
+#
+
+require_git_repo() {
+ if ! git rev-parse --git-dir >/dev/null 2>&1; then
+ die "fatal: Not a git repository"
+ fi
+}
+
+require_gitflow_initialized() {
+ if ! gitflow_is_initialized; then
+ die "fatal: Not a gitflow-enabled repo yet. Please run \"git flow init\" first."
+ fi
+}
+
+require_clean_working_tree() {
+ git_is_clean_working_tree
+ local result=$?
+ if [ $result -eq 1 ]; then
+ die "fatal: Working tree contains unstaged changes. Aborting."
+ fi
+ if [ $result -eq 2 ]; then
+ die "fatal: Index contains uncommited changes. Aborting."
+ fi
+}
+
+require_local_branch() {
+ if ! git_local_branch_exists $1; then
+ die "fatal: Local branch '$1' does not exist and is required."
+ fi
+}
+
+require_remote_branch() {
+ if ! has $1 $(git_remote_branches); then
+ die "Remote branch '$1' does not exist and is required."
+ fi
+}
+
+require_branch() {
+ if ! has $1 $(git_all_branches); then
+ die "Branch '$1' does not exist and is required."
+ fi
+}
+
+require_branch_absent() {
+ if has $1 $(git_all_branches); then
+ die "Branch '$1' already exists. Pick another name."
+ fi
+}
+
+require_tag_absent() {
+ if has $1 $(git_all_tags); then
+ die "Tag '$1' already exists. Pick another name."
+ fi
+}
+
+require_branches_equal() {
+ require_local_branch "$1"
+ require_remote_branch "$2"
+ git_compare_branches "$1" "$2"
+ local status=$?
+ if [ $status -gt 0 ]; then
+ warn "Branches '$1' and '$2' have diverged."
+ if [ $status -eq 1 ]; then
+ die "And branch '$1' may be fast-forwarded."
+ elif [ $status -eq 2 ]; then
+ # Warn here, since there is no harm in being ahead
+ warn "And local branch '$1' is ahead of '$2'."
+ else
+ die "Branches need merging first."
+ fi
+ fi
+}
diff --git a/gitflow-feature b/gitflow-feature
deleted file mode 100755
index 90c9f4c..0000000
--- a/gitflow-feature
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/sh
-#
-# gitflow -- A collection of Git wrapper scripts to provide high-level
-# repository operations for Vincent Driessen's branching model:
-#
-# Original blog post presenting this model is found at:
-# http://nvie.com/archives/323
-#
-# Feel free to contribute to this project at:
-# http://github.com/nvie/gitflow
-#
-# Copyright (c) 2010 by Vincent Driessen
-#
-
-usage() {
- echo "usage: gitflow start feature [<options>] <name> [<base>]"
- echo " gitflow finish feature [<options>] <name>"
- # TODO
- #echo ""
- #echo "options:"
- #echo "--option Explanation"
- #echo ""
- #echo "start-only options:"
- #echo "--option Explanation"
- #echo ""
- #echo "finish-only options:"
- #echo "--rebase Rebases the feature branch on top of develop, instead of merging"
- #echo "--squash Squashes all commits of the feature branch into a single commit"
- #echo " on develop"
- #echo "--push Push to the origin repo when finished"
-}
-
-parse_args() {
- FEATURE="$1"
- if [ $# -eq 2 ]; then
- BASE="$2"
- else
- BASE="develop"
- fi
- if [ "$FEATURE" = "" ]; then
- echo "Missing argument <release>"
- usage
- exit 1
- fi
-}
-
-start() {
- parse_args "$@"
-
- # Checks
- gitflow_check_clean_working_tree
- gitflow_require_branch_absent "$FEATURE"
- if [ "$BASE" = "develop" ]; then
- gitflow_require_branches_equal 'develop' 'origin/develop'
- fi
-
- # All checks passed, ready to roll
- git checkout -b "$FEATURE" "$BASE"
-
- echo ""
- echo "Summary of actions:"
- echo "- A new branch '$FEATURE' was created, based on '$BASE'"
- echo "- You are now on branch '$FEATURE'"
- echo ""
- echo "Now, start committing on your feature. When done, use:"
- echo ""
- echo " gitflow finish feature '$FEATURE'"
-}
-
-finish() {
- parse_args "$@"
-
- # Checks
- gitflow_check_clean_working_tree
- gitflow_require_branch "$FEATURE"
- gitflow_require_branches_equal 'develop' 'origin/develop'
-
- # All checks passed, ready to roll
- git checkout develop
-
- # In case there has been only a single commit in the feature branch, don't
- # use --no-ff, since it has no extra advantages
- FF_FLAG="--no-ff"
- if [ "$(git rev-list develop.."$FEATURE" | wc -l)" -eq 1 ]; then
- FF_FLAG="--ff"
- fi
- git merge "$FF_FLAG" "$FEATURE"
- # TODO: How do we handle merge conflicts here??
- git branch -d "$FEATURE"
-
- echo ""
- echo "Summary of actions:"
- echo "- The feature branch '$FEATURE' was merged into 'develop'"
- #echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported
- echo "- Feature branch '$FEATURE' has been removed"
- echo "- You are now on branch 'develop'"
- echo ""
-}
-
diff --git a/gitflow-hotfix b/gitflow-hotfix
deleted file mode 100755
index b1e8834..0000000
--- a/gitflow-hotfix
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/sh
-#
-# gitflow -- A collection of Git wrapper scripts to provide high-level
-# repository operations for Vincent Driessen's branching model:
-#
-# Original blog post presenting this model is found at:
-# http://nvie.com/archives/323
-#
-# Feel free to contribute to this project at:
-# http://github.com/nvie/gitflow
-#
-# Copyright (c) 2010 by Vincent Driessen
-#
-
-usage() {
- echo "usage: gitflow start hotfix <release>"
- echo " gitflow finish hotfix <release>"
- # TODO
- #echo ""
- #echo "options:"
- #echo "--option Explanation"
- #echo ""
- #echo "start-only options:"
- #echo "--option Explanation"
- #echo ""
- #echo "finish-only options:"
- #echo "--push Push to the origin repo when finished"
-}
-
-parse_args() {
- RELEASE="$1"
- if [ "$RELEASE" = "" ]; then
- echo "Missing argument <release>"
- usage
- exit 1
- fi
- HOTFIX_BRANCH="hotfix-$RELEASE"
-}
-
-start() {
- parse_args "$@"
-
- # Checks
- gitflow_check_clean_working_tree
- gitflow_require_branches_equal 'master' 'origin/master'
- gitflow_require_branch_absent "$HOTFIX_BRANCH"
-
- # All checks passed, ready to roll
- git checkout -b "$HOTFIX_BRANCH" master
-
- echo ""
- echo "Summary of actions:"
- echo "- A new branch '$HOTFIX_BRANCH' was created, based on 'master'"
- echo "- You are now on branch '$HOTFIX_BRANCH'"
- echo ""
- echo "Follow-up actions:"
- echo "- Bump the version number now!"
- echo "- Start committing your hot fixes"
- echo "- When done, run:"
- echo ""
- echo " gitflow finish hotfix '$HOTFIX_BRANCH'"
-}
-
-finish() {
- parse_args "$@"
-
- # Checks
- gitflow_check_clean_working_tree
-
- git fetch origin develop # TODO: Make a flag to skip these fetches
- git fetch origin master # TODO: Make a flag to skip these fetches
- gitflow_require_branches_equal 'master' 'origin/master'
- gitflow_require_branches_equal 'develop' 'origin/develop'
-
- # All checks passed, ready to roll
- git checkout master
- git merge --no-ff "$HOTFIX_BRANCH"
- git tag "$RELEASE"
- git checkout develop
- git merge --no-ff "$HOTFIX_BRANCH"
- git branch -d "$HOTFIX_BRANCH"
-
- # TODO: Implement an optional push to master
- # git push origin develop; git push origin master; git push --tags origin
-
- echo ""
- echo "Summary of actions:"
- echo "- Latest objects have been fetched from 'origin'"
- echo "- Hotfix branch has been merged into 'master'"
- echo "- The hotfix was tagged '$RELEASE'"
- echo "- Hotfix branch has been back-merged into 'develop'"
- echo "- Hotfix branch '$HOTFIX_BRANCH' has been deleted"
- echo ""
-}
-
diff --git a/gitflow-release b/gitflow-release
deleted file mode 100755
index b4f2424..0000000
--- a/gitflow-release
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/sh
-#
-# gitflow -- A collection of Git wrapper scripts to provide high-level
-# repository operations for Vincent Driessen's branching model:
-#
-# Original blog post presenting this model is found at:
-# http://nvie.com/archives/323
-#
-# Feel free to contribute to this project at:
-# http://github.com/nvie/gitflow
-#
-# Copyright (c) 2010 by Vincent Driessen
-#
-
-usage() {
- echo "usage: gitflow start release <release>"
- echo " gitflow finish release <release>"
- # TODO
- #echo ""
- #echo "options:"
- #echo "--option Explanation"
- #echo ""
- #echo "start-only options:"
- #echo "--bump <script>"
- #echo " Run the given script to auto-update the version number"
- #echo ""
- #echo "finish-only options:"
- #echo "--push Push to the origin repo when finished"
-}
-
-parse_args() {
- RELEASE="$1"
- if [ "$RELEASE" = "" ]; then
- echo "Missing argument <release>"
- usage
- exit 1
- fi
- RELEASE_BRANCH="release-$RELEASE"
-}
-
-start() {
- parse_args "$@"
-
- # Checks
- gitflow_check_clean_working_tree
- gitflow_require_branches_equal 'develop' 'origin/develop'
- gitflow_require_branch_absent "$RELEASE_BRANCH"
-
- # All checks passed, ready to roll
- git checkout -b "$RELEASE_BRANCH" develop
-
- echo ""
- echo "Summary of actions:"
- echo "- A new branch '$RELEASE_BRANCH' was created, based on 'develop'"
- echo "- You are now on branch '$RELEASE_BRANCH'"
- echo ""
- echo "Follow-up actions:"
- echo "- Bump the version number now!"
- echo "- Start committing last-minute fixes in preparing your release"
- echo "- When done, run:"
- echo ""
- echo " gitflow finish release '$RELEASE_BRANCH'"
-}
-
-finish() {
- parse_args "$@"
-
- # Checks
- gitflow_check_clean_working_tree
-
- git fetch origin develop # TODO: Make a flag to skip these fetches
- git fetch origin master # TODO: Make a flag to skip these fetches
- gitflow_require_branches_equal 'master' 'origin/master'
- gitflow_require_branches_equal 'develop' 'origin/develop'
-
- # All checks passed, ready to roll
- git checkout master
- git merge --no-ff "$RELEASE_BRANCH"
- git tag "$RELEASE"
- git checkout develop
- git merge --no-ff "$RELEASE_BRANCH"
- git branch -d "$RELEASE_BRANCH"
-
- # TODO: Implement an optional push to master
- # git push origin develop; git push origin master; git push --tags origin
-
- echo ""
- echo "Summary of actions:"
- echo "- Latest objects have been fetched from 'origin'"
- echo "- Release branch has been merged into 'master'"
- echo "- The release was tagged '$RELEASE'"
- echo "- Release branch has been back-merged into 'develop'"
- echo "- Release branch '$RELEASE_BRANCH' has been deleted"
- echo ""
-}
-
diff --git a/gitflow-sh-setup b/gitflow-sh-setup
deleted file mode 100755
index 0826758..0000000
--- a/gitflow-sh-setup
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/bin/sh
-#
-# gitflow -- A collection of Git wrapper scripts to provide high-level
-# repository operations for Vincent Driessen's branching model:
-#
-# Original blog post presenting this model is found at:
-# http://nvie.com/archives/323
-#
-# Feel free to contribute to this project at:
-# http://github.com/nvie/gitflow
-#
-# Copyright (c) 2010 by Vincent Driessen
-#
-
-# Get the git dir
-GIT_DIR=$(git rev-parse --git-dir)
-
-# Get all available branches
-LOCAL_BRANCHES=$(git branch | sed 's/^[* ] //')
-REMOTE_BRANCHES=$(git branch -r | sed 's/^[* ] //')
-ALL_BRANCHES="$LOCAL_BRANCHES\n$REMOTE_BRANCHES"
-
-warn() { echo "$@" >&2; }
-die() { warn "$@"; exit 1; }
-
-gitflow_check_clean_working_tree() {
- if [ "$(git status 2>/dev/null | tail -n1)" != "nothing to commit (working directory clean)" ]; then
- die "Working directory is dirty. Only use gitflow in clean working directories for your own safety."
- fi
-}
-
-gitflow_require_local_branch() {
- echo "$LOCAL_BRANCHES" | grep "^$1\$" 2>&1 >/dev/null
- if [ $? -ne 0 ]; then
- die "Local branch '$1' does not exist and is required."
- fi
-}
-
-gitflow_require_remote_branch() {
- echo "$REMOTE_BRANCHES" | grep "^$1\$" 2>&1 >/dev/null
- if [ $? -ne 0 ]; then
- die "Remote branch '$1' does not exist and is required."
- fi
-}
-
-gitflow_require_branch() {
- echo "$ALL_BRANCHES" | grep "^$1\$" 2>&1 >/dev/null
- if [ $? -ne 0 ]; then
- die "Branch '$1' does not exist and is required."
- fi
-}
-
-gitflow_require_branch_absent() {
- echo "$ALL_BRANCHES" | grep "^$1\$" 2>&1 >/dev/null
- if [ $? -eq 0 ]; then
- die "Branch '$1' already exists. Pick another name."
- fi
-}
-
-#
-# gitflow_test_branches_equal()
-#
-# Tests whether branches and their "origin" counterparts have diverged and need
-# merging first. It returns error codes to provide more detail, like so:
-#
-# 0 Branch heads point to the same commit
-# 1 First given branch needs fast-forwarding
-# 2 Second given branch needs fast-forwarding
-# 3 Branch needs a real merge
-#
-gitflow_test_branches_equal() {
- commit1=$(git rev-parse "$1")
- commit2=$(git rev-parse "$2")
- if [ "$commit1" != "$commit2" ]; then
- base=$(git merge-base "$commit1" "$commit2")
- short_base=$(git rev-parse --short "$base")
-
- if [ "$commit1" = "$base" ]; then
- return 1
- elif [ "$commit2" = "$base" ]; then
- return 2
- else
- return 3
- fi
- else
- return 0
- fi
-}
-
-gitflow_require_branches_equal() {
- gitflow_require_local_branch "$1"
- gitflow_require_remote_branch "$2"
- gitflow_test_branches_equal "$1" "$2"
- status=$?
- if [ $status -gt 0 ]; then
- warn "Branches '$1' and '$2' have diverged."
-
- if [ $status -eq 1 ]; then
- die "And branch '$1' may be fast-forwarded."
- elif [ $status -eq 2 ]; then
- # Warn here, since there is no harm in being ahead
- warn "And local branch '$1' is ahead of '$2'."
- else
- die "Branches need merging first."
- fi
- fi
-}
-
diff --git a/gitflow-shFlags b/gitflow-shFlags
new file mode 120000
index 0000000..7b736c1
--- /dev/null
+++ b/gitflow-shFlags
@@ -0,0 +1 @@
+shFlags/src/shflags
\ No newline at end of file
diff --git a/gitflow-version b/gitflow-version
deleted file mode 100644
index c375924..0000000
--- a/gitflow-version
+++ /dev/null
@@ -1 +0,0 @@
-GITFLOW_VERSION=0.1
diff --git a/shFlags b/shFlags
new file mode 160000
index 0000000..2fb06af
--- /dev/null
+++ b/shFlags
@@ -0,0 +1 @@
+Subproject commit 2fb06af13de884e9680f14a00c82e52a67c867f1