I found [nvie's git branching model](http://nvie.com/posts/a-successful-git-branching-model/) suitable for my work - but the frontend supplied at GitHub was too complex for me to understand. Hence, I wrote this script to start and finish tasks, automatically running the related commands to speed it all up a bit (without it becoming *too* abstract/complex).

I've read a handful of tutorials - on writing shell scripts - scattered across the web but found it difficult to find one that emphasized on portability/POSIX compliancy. I'd like the script to run just fine in sh, dash, bash and zsh. Any feedback appreciated. (I'm a bit unsure about where to use $variable and ${variable} too.)

Intended usage
==============
When I want to create a new branch for a task I run this:

    gtask.sh start feature name_of_feature

When I'm done:

    gtask.sh finish

Finishing a task has it automatically deduce by the branch name prefix (feature/release/hotfix) what to do next.

* Features are merged back into the development branch.
* Releases are continuously merged back into the development branch (bugfixes) and then, once per release branch, merged into master (with a tag).
* Hotfixes are merged back into both the master (with a tag) and the development branch. 

The branch model
================
I use two persistent/remote branches, master and development, as well as three temporary/local branches, feature, release and hotfix.

**Master branch**

* Persistent
* Remote branch
* Each merge into master equals a new tag

**Development branch**

* Persistent
* Remote branch

**Feature branches**

* Temporary
* Branch off from development
* Merge back into development
* Naming: "subject" or "issue#" if on issue tracker ("feature/" is prepended)

**Release branches**

* Temporary
* Branch off from development
* Merge back into development (continuously) and master (when done)
* Naming: "major.minor.z", e.g. "1.2.0" (z is defined by hotfix, "release/" is prepended)
* Signed tag needed when merging with master

**Hotfix branches**

* Temporary
* Branch off from master
* Merge back into development and master
* Naming: "x.y.fix", e.g. "1.2.1" (x, y is defined by release, "hotfix/" is prepended)
* Signed tag needed when merging with master

The script
==========

    #!/bin/sh
    # gtask: start and finish new feature, hotfix or release branches
    
    usage()
    {
        echo "Usage:"
        echo "  gtask start feature name_of_feature"
        echo "  gtask start release name_of_release"
        echo "  gtask start hotfix name_of_hotfix"
        echo "  gtask finish (affects current branch)"
    }
    
    delete_branch()
    {
        echo "Delete branch $current?";
        select yn in "Yes" "No"; do
            case $yn in
                Yes )
                    echo "Deleting branch $current."
                    git branch -d ${current}
                    ;;
                No )
                    echo "Leaving branch $current as it is."
                    ;;
            esac
        done
    }
    
    define_tag()
    {
        while [ -z ${version_number} && -z ${version_note} ]; do
            echo "Enter version number (major.minor.fix): "
            read version_number
            echo "Enter version number note: "
            read version_note
        done
    }
    
    if [ "$1" == "start" ]; then
        case $2 in
            feature )
                git checkout development
                git checkout -b "feature/$2"
                ;;
            release )
                git checkout development
                git checkout -b "release/$2"
                ;;
            hotfix )
                git checkout master
                git checkout -b "hotfix/$2"
                ;;
            * )
                echo "Error: You didn't specify feature, release or hotfix."
                usage
                exit 1
                ;;
        esac
    elif [ "$1" == "finish" ]; then
        current=`git branch | awk '/\*/{print $2}'`
        case ${current} in
            feature* )
                git checkout development
                git merge ${current}
                git push origin development
                delete_branch
                ;;
    
            release* )
                echo "Merging into development..."
                git checkout development
                git merge ${current}
                git push origin development
                echo "Merge into master (make a release)?"
                select yn in "Yes" "No"; do
                    case $yn in
                        Yes )
                            git checkout master
                            git merge ${current}
                            define_tag
                            git tag -s $version_number -m $version_note
                            git push --tags origin master
                            delete_branch
                            ;;
                        No )
                            echo "..."
                            ;;
                    esac
                done
                ;;
            
            hotfix* )
                git checkout master
                git merge ${current}
                define_tag
                git tag -s $version_number -m $version_note
                git push --tags origin master
                git checkout development
                git merge ${current}
                git push origin development
                delete_branch
                ;;
        
            * )
                echo "Error: Not on a feature, release or hotfix branch."
                usage
                exit 1
                ;;
        esac
    else
        usage
        exit 1
    fi