In my company I follow the following workflow. (I think it can be defined a kind of 'Continuous Integration'.)Workflow: We have 3 fixed branches (staging/master/production)  Every push to staging or production automatically deploy to staging/production server.We use git in the following way:(suppose I'm working on the new functionality 'A')I create a new branch from Master (ex. branch 'A')If I want to show my changes to the client I merge A to staging and push it.once finish my work on A I merge back A on Master and push masterto send changes live I merge Master in Production branch and push productionI find quite boring/time consuming to git checkout ... git pull .. bla bla every time I have to deploy live/staging my work.So I have produced the following bash script, the aim is to simplify the process of deploying branch A into a single command deploy.sh live A#!/bin/bashfunction merge() {      SOURCE=$1    DEST=$2    echo ''    echo --- Merging $SOURCE with $DEST ---     echo --> Checkout $DEST ...     git checkout $DEST    echo --> Pull $DEST ...    git pull --ff-only origin $DEST    if [ $? -ne 0 ]    then      echo ERROR: Could not PULL      return 1    fi    echo --> Merging $SOURCE with $DEST ...     git merge --ff-only $SOURCE --no-edit  # --ff-only trigger errors if merge/pull is not possible    if [ $? -ne 0 ]    then      echo ERROR: Could not MERGE      return 1    fi    echo --> Push $DEST ...    git push origin $DEST    return 0}function deploy() {    MODE=$1    SOURCE_BRANCH=$2    echo ''    echo ### START ###    echo ''    echo --- Pull changes from Master ---    git checkout $SOURCE_BRANCH    git pull --progress --no-edit --no-stat -v --progress origin master    merge $SOURCE_BRANCH 'staging'    status=$?    if [ $status -ne 0 ]    then      echo ERROR: STEP 1 >&2      exit 1    fi    if [ $MODE = live ]    then        merge $SOURCE_BRANCH 'master'        status=$?        if [ $status -ne 0 ]        then          echo ERROR: STEP 2          return 1        fi        merge 'master' 'production'        status=$?        if [ $status -ne 0 ]        then          echo ERROR: STEP 3          return 1        fi    fi    echo ''    echo ### END ###    echo ''}MODE=$1;SOURCE_BRANCH=$2;if [ -z $MODE  -o -z $SOURCE_BRANCH ]    then        echo Usage:        echo         echo  MODE BRANCH_NAME (MODE: live|staging)    else        if git show-ref --verify --quiet refs/heads/$SOURCE_BRANCH;        # if [ `git branch --list $SOURCE_BRANCH ` ]            then                deploy $MODE $SOURCE_BRANCH        else            echo ''            echo Error: Branch $SOURCE_BRANCH not found        fifiThe question: I'm quite newby both on GIT and BASH scripting. So I would like to know if the above workflow/script is ok ? Any recommendation is welcome.(I'm happy to share this as resource.)
Bash script to simplify Git deployment workflow
beginner;bash;git
Use exit codes directlyInstead of this:merge $SOURCE_BRANCH 'staging'status=$?if [ $status -ne 0 ]then  echo ERROR: STEP 1 >&2  exit 1fiYou can use exit codes directly in conditions, like this:if ! merge $SOURCE_BRANCH 'staging'then  echo ERROR: STEP 1 >&2  exit 1fiUse it this way everywhere.Handle errors consistentlyThe error handling is inconsistent throughout the script:Sometimes you exit 1, sometimes you return 1 in functions. It would be better to do consistentlySometimes you print the error message on stdout, sometimes on stderr. It would be better to print it consistently on stderrStyleTo print a blank line you can simply echo without a parameter.You can drop return 0 as the last statement of a function. The exit code of the last  statement will be used as the exit code of the function.A semicolon is unnecessary at the end of the line.Long comments at the end of a line are generally hard to read. Move these to the previous line.The indentation is not consistent. The code inside the functions looks nice, do the same way for the code outside.Ex. ( edited by @WonderLand)#!/bin/bashfunction merge() {      SOURCE=$1    DEST=$2    echo    echo ---> Merging $SOURCE with $DEST     echo    echo ---> ---> Checkout $DEST ...         git checkout $DEST    echo    echo ---> ---> Pull $DEST ...    if ! git pull --ff-only origin $DEST    then     exit 1    fi    echo    echo ---> ---> Merging $SOURCE with $DEST ...     # --ff-only trigger errors if merge/pull is not possible    if ! git merge --ff-only $SOURCE --no-edit    then      exit 1    fi    echo    echo ---> ---> Push $DEST ...    git push origin $DEST}function deploy() {    MODE=$1    SOURCE_BRANCH=$2    echo         echo ---> Pull changes from Master ...    if ! git checkout $SOURCE_BRANCH    then            exit 1    fi    git pull --progress --no-edit --no-stat -v --progress origin master    if ! merge $SOURCE_BRANCH 'staging'    then            exit 1    fi    if [ $MODE = live ]    then        if ! merge $SOURCE_BRANCH 'master'        then                    exit 1        fi        if ! merge 'master' 'production'        then                    exit 1        fi    fi}MODE=$1SOURCE_BRANCH=$2if [ -z $MODE  -o -z $SOURCE_BRANCH ]then    echo Usage:    echo     echo  MODE BRANCH_NAME (MODE: live|staging)else    if git show-ref --verify --quiet refs/heads/$SOURCE_BRANCH    then        echo        echo ### START ###        echo        deploy $MODE $SOURCE_BRANCH        echo        echo ### END ###        echo    else        echo        echo Error: Branch $SOURCE_BRANCH not found    fifi