Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Subcommand: Issues #297

Open
wants to merge 5 commits into from

1 participant

@johnbellone

While discussing implementing a trial of the branching model we are looking to involve our QA team to sign-off on issues, and to have the infrastructure/release managers to have an easier time backing out releases. This is leading us to not perform any actual development on the develop branch, but rather treat it as an integration point.

The easiest way we thought to do this was to open up a command that allowed for managing issues directly in the repository. Once they are published they would be "finished" by the testers to officially sign off on the feature and this would trigger a merge into the integration branch. Once integration was at at stable point a release branch could be cut, and that would be on the bus to production.

johnbellone added some commits
@johnbellone johnbellone Basic support for issues subcommand.
For now just made a blind copy of the hotfix command. Going to support some additional features
but this is a good basis to begin from.
47d7cbe
@johnbellone johnbellone Fixing a little something to get working.
A few syntax errors and adding in support for issue initial phase to setup the prefix.
2324a61
@johnbellone johnbellone Merging more of the feaeture commands into issue.
- This mimics less of a hotfix and more of a feature. There's still some tweaking but
basically should work very similar now.
b3cfcdc
@johnbellone johnbellone Adding my name to Authors list.' 403956c
@johnbellone johnbellone Updating the README.mdown with issue branches.
This was an oversight on my part. Update this to give an example like the rest of the
comands.
0fadbe0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 2, 2013
  1. @johnbellone

    Basic support for issues subcommand.

    johnbellone authored
    For now just made a blind copy of the hotfix command. Going to support some additional features
    but this is a good basis to begin from.
  2. @johnbellone

    Fixing a little something to get working.

    johnbellone authored
    A few syntax errors and adding in support for issue initial phase to setup the prefix.
  3. @johnbellone

    Merging more of the feaeture commands into issue.

    johnbellone authored
    - This mimics less of a hotfix and more of a feature. There's still some tweaking but
    basically should work very similar now.
Commits on Feb 3, 2013
  1. @johnbellone
Commits on Feb 5, 2013
  1. @johnbellone

    Updating the README.mdown with issue branches.

    johnbellone authored
    This was an oversight on my part. Update this to give an example like the rest of the
    comands.
This page is out of date. Refresh to see the latest.
View
1  AUTHORS
@@ -20,5 +20,6 @@ Authors are (ordered by first commit date):
- Eric Holmes
- Vedang Manerikar
- Myke Hines
+- John Bellone
Portions derived from other open source works are clearly marked.
View
5 README.mdown
@@ -132,6 +132,11 @@ The ``-d`` flag will accept all defaults.
For support branches, the `<base>` arg must be a commit on `master`.
+* To list/start issue branches, use:
+ `git flow issue`
+ `git flow issue start <name> [<base>]`
+
+ For issue branches, the `<base>` arg must be a commit on `develop`.
Showing your appreciation
=========================
View
1  git-flow
@@ -57,6 +57,7 @@ usage() {
echo " feature Manage your feature branches."
echo " release Manage your release branches."
echo " hotfix Manage your hotfix branches."
+ echo " issue Manage your issue branches."
echo " support Manage your support branches."
echo " version Shows version information."
echo
View
13 git-flow-init
@@ -233,6 +233,7 @@ cmd_default() {
! 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.issue >/dev/null 2>&1 ||
! git config --get gitflow.prefix.support >/dev/null 2>&1 ||
! git config --get gitflow.prefix.versiontag >/dev/null 2>&1; then
echo
@@ -281,6 +282,18 @@ cmd_default() {
git_do config gitflow.prefix.hotfix "$prefix"
fi
+ # Issue branches
+ if ! git config --get gitflow.prefix.issue >/dev/null 2>&1 || flag force; then
+ default_suggestion=$(git config --get gitflow.prefix.issue || echo issue/)
+ printf "Issue branches? [$default_suggestion] "
+ if noflag defaults; then
+ read answer
+ else
+ printf "\n"
+ fi
+ [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
+ git_do config gitflow.prefix.issue "$prefix"
+ fi
# Support branches
if ! git config --get gitflow.prefix.support >/dev/null 2>&1 || flag force; then
View
444 git-flow-issue
@@ -0,0 +1,444 @@
+#
+# 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.issue)
+}
+
+usage() {
+ echo "usage: git flow issue [list] [-v]"
+ echo " git flow issue start -F <name> [<base>]"
+ echo " git flow issue finish [-FkDS] [<name|nameprefix>]"
+ echo " git flow issue publish <name>"
+ echo " git flow issue track <name>"
+ echo " git flow issue pull [-r] <remote> [<name>]"
+}
+
+cmd_default() {
+ cmd_list "$@"
+}
+
+cmd_list() {
+ DEFINE_boolean verbose false 'verbose (more) output' v
+ parse_args "$@"
+
+ local issue_branches
+ local current_branch
+ local short_names
+ issue_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
+ if [ -z "$issue_branches" ]; then
+ warn "No issue branches exist."
+ warn ""
+ warn "You can start a new issue branch:"
+ warn ""
+ warn " git flow issue start <name> [<base>]"
+ warn ""
+ exit 0
+ fi
+ current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
+ short_names=$(echo "$issue_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 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
+ 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
+}
+
+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
+}
+
+require_base_is_on_develop() {
+ if ! git branch --no-color --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
+}
+
+cmd_start() {
+ DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
+ parse_args "$@"
+ BASE=${2:-$DEVELOP_BRANCH}
+ require_name_arg
+ require_base_is_on_develop
+
+ # sanity checks
+ require_clean_working_tree
+ require_branch_absent "$BRANCH"
+
+ # update the local repo with remote changes, if asked
+ if flag fetch; then
+ git_do 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_do checkout -b "$BRANCH" "$BASE"; then
+ die "Could not create issue 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 "Follow-up actions:"
+ echo "- Start committing on your issue."
+ echo "- To publish your changes for testing:"
+ echo " git flow issue publish '$NAME'"
+ echo "- When done, use:"
+ echo " git flow issue finish '$NAME'"
+ echo
+}
+
+cmd_publish() {
+ parse_args "$@"
+ require_name_arg
+
+ # sanity checks
+ require_clean_working_tree
+ require_branch "$BRANCH"
+ git_do fetch -q "$ORIGIN"
+ require_branch_absent "$ORIGIN/$BRANCH"
+
+ # create remote branch
+ git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
+ git_do fetch -q "$ORIGIN"
+
+ # configure remote tracking
+ git config "branch.$BRANCH.remote" "$ORIGIN"
+ git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
+ git_do 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_do fetch -q "$ORIGIN"
+ require_branch "$ORIGIN/$BRANCH"
+
+ # create tracking branch
+ git_do 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_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 issue branch after finish" D
+ DEFINE_boolean squash false "squash issue during merge" S
+ 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 issue 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_do fetch -q "$ORIGIN" "$BRANCH"
+ git_do 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
+
+ # 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"
+ else
+ if noflag squash; then
+ git_do merge --no-ff "$BRANCH"
+ else
+ git_do merge --squash "$BRANCH"
+ git_do commit
+ git_do 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 issue finish $NAME"
+ echo
+ exit 1
+ fi
+
+ # when no merge conflict is detected, just clean up the issue branch
+ helper_finish_cleanup
+}
+
+helper_finish_cleanup() {
+ # sanity checks
+ require_branch "$BRANCH"
+ require_clean_working_tree
+
+ # delete branch
+ if flag fetch; then
+ git_do push "$ORIGIN" ":refs/heads/$BRANCH"
+ fi
+
+ if noflag keep; then
+ if flag force_delete; then
+ git_do branch -D "$BRANCH"
+ else
+ git_do branch -d "$BRANCH"
+ fi
+ fi
+
+ echo
+ echo "Summary of actions:"
+ echo "- The issue branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
+ if flag keep; then
+ echo "- Issue branch '$BRANCH' is still available"
+ else
+ echo "- Issue branch '$BRANCH' has been removed"
+ fi
+ echo "- You are now on branch '$DEVELOP_BRANCH'"
+ echo
+}
+
+cmd_pull() {
+ #DEFINE_string prefix false 'alternative remote issue 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 issue branches into each other,
+ # die if the current issue branch differs from the requested $NAME
+ # argument.
+ local current_branch=$(git_current_branch)
+ if startswith "$current_branch" "$PREFIX"; then
+ # we are on a local issue 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_do 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'."
+ 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."
+ echo "Created local branch $BRANCH based on $REMOTE's $BRANCH."
+ fi
+}
View
1  gitflow-common
@@ -179,6 +179,7 @@ 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.issue >/dev/null 2>&1 && \
git config --get gitflow.prefix.support >/dev/null 2>&1 && \
git config --get gitflow.prefix.versiontag >/dev/null 2>&1
}
Something went wrong with that request. Please try again.