Gitgo or: How I learned to live with VCS

This is way out of date now

The information in this post is so out-dated that I wonder why I'm keeping it around. I guess I'm a digital hoarder...

UPDATE

Only keeping thins post around as a reminder of how far I've come.

UPDATE

This is a bit outdated now, as I have added some features and polished up the code a bit. I will post the update after the migration to Ghost is done.

UPDATE

Changed order of main to try to avoid push conflicts

UPDATE

Multi-directory bug squashed! (I think)

UPDATE

Found a bug that breaks the script if you are deep in a multi-directory Git repo and call this script. (All of my repos are currently only one directory deep, so it might be a bit before I squash this bug...)


Personally, I've never been one to use a version control system. Even during university, when it was a 'requirement' to use such a system, I opted out and used either no version control at all or Google Docs.

I didn't know what I was missing.

I have started using Git in my professional career, and I have to say I'm hooked. I'm just not overly fond of one aspect of Git. The commands.

Sure, after using it day in and day out it became less of a chore and more of a required familiarity, but I still wanted a better way so I decided to write a script in bash to help streamline my interactions with git.

#!/bin/bash - 
#===============================================================================
#
#          FILE: gitgo.rewrite.sh
# 
#         USAGE: ./gitgo.rewrite.sh 
# 
#   DESCRIPTION: 
# 
#       OPTIONS: ---
#  REQUIREMENTS: ---
#          BUGS: ---
#         NOTES: ---
#  ORGANIZATION: 
#       CREATED: 01/25/2013 01:46:29 PM CST
#      REVISION:  ---
#===============================================================================
#-------------------------------------------------------------------------------
#  Set Colors for pretty output
#-------------------------------------------------------------------------------
txtred=$(tput setaf 1) # Red
txtgrn=$(tput setaf 2) # Green
txtylw=$(tput setaf 3) # Yellow
txtwht=$(tput setaf 7) # White
txtrst=$(tput sgr0) # Text reset.

#-------------------------------------------------------------------------------
#  Trap Control-C and react by resetting HEAD for git
#-------------------------------------------------------------------------------
    trap control_c SIGINT
    control_c(){
          echo -en "\n*** Ctrl^c caught.  Exiting ***\n"
            git reset HEAD;
              exit 1
    }

#-------------------------------------------------------------------------------
# Main Case Statement for setting flags 
#-------------------------------------------------------------------------------
flags=$1
case "$flag" in
    -y)
        answer=$flag;;
    -h)
        echo "Help Documentation HERE";;
    "")
        echo "No Flags" > /dev/null ;;
    *)
        echo "Invalid Flag";;
esac

#-------------------------------------------------------------------------------
#  Check if you are in a Git Reop, and fail/exit if not
#-------------------------------------------------------------------------------
    isGit(){
        check_repo=`git rev-parse --is-inside-work-tree`
        if [ "$check_repo" == "true" ]
            then
                git_base_dir=`git rev-parse --show-toplevel`
                cd $git_base_dir
                main
            else
                echo "Not a git repository!"
                exit
        fi
    }

    gitLists(){
    #-------------------------------------------------------------------------------
    # Set Internal Field Seperator to NewLine 
    #-------------------------------------------------------------------------------
        IFS=$'\n'
    #-------------------------------------------------------------------------------
    #  Get list of untracked files
    #-------------------------------------------------------------------------------
        N=0
        for i in $(git ls-files -o) ; do
            #j="${git_base_dir}/$i"
            untracked[$N]="$i"
            let "N= $N + 1"
        done

    #-------------------------------------------------------------------------------
    #  Get list of modified files
    #-------------------------------------------------------------------------------
        N=0
        for i in $(git diff --name-only --diff-filter=M) ; do
            #j=`basename $i`
            #modified[$N]="$j"
            j="${git_base_dir}/$i"
            modified[$N]="$j"
            let "N= $N + 1"
        done

    #-------------------------------------------------------------------------------
    #  Get list of renamed files
    #-------------------------------------------------------------------------------
        N=0
        for i in $(git diff --name-only --diff-filter=R) ; do
            #j=`basename $i`
            #modified[$N]="$j"
            j="${git_base_dir}/$i"
            renamed[$N]="$j"
            let "N= $N + 1"
        done
    #-------------------------------------------------------------------------------
    #  Get list of delted files
    #-------------------------------------------------------------------------------
        N=0
        for i in $(git ls-files --deleted) ; do
            deleted[$N]="$i"
            let "N= $N + 1"
        done

    }

    gitStage(){
    #-------------------------------------------------------------------------------
    #  Check for array lengths of 0
    #-------------------------------------------------------------------------------
        length_untracked=${#untracked[@]}
        length_modified=${#modified[@]}
        length_renamed=${#renamed[@]}
        length_deleted=${#deleted[@]}

        echo "$txtwht************** Changes **************$txtrst"
        if [ $length_untracked -eq 0 ]
            then
                echo "$txtylw No new or untracked files found $txtrst"
            else
                for i in "${untracked[@]}"
                do
                    echo -e "$txtgrn Adding new file: $i $txtrst"
                    git add $i
                done
        fi

        if [ $length_modified -eq 0 ]
            then
                echo "$txtylw No modified files found $txtrst"
            else
                for i in "${modified[@]}"
                do
                    echo -e "$txtgrn Updating modified file: $i $txtrst"
                    git add $i
                done
        fi

        if [ $length_renamed -eq 0 ]
            then
                echo "$txtylw No renamed files found $txtrst"
            else
                for i in "${renamed[@]}"
                do
                    echo -e "$txtgrn Adding renamed file: $i $txtrst"
                    git add $i
                done
        fi

        if [ $length_deleted -eq 0 ]
            then
                echo "$txtylw No deleted files found $txtrst"
            else
                for i in "${deleted[@]}"
                do
                    echo "$txtred Removing deleted file: $i $txtrst"
                    git rm $i
                done
        fi
        echo "$txtwht*************************************$txtrst"
    }

    gitGo(){
    #-------------------------------------------------------------------------------
    #  Ask to commit changes
    #-------------------------------------------------------------------------------

        if [ $length_untracked -eq 0 ] && [ $length_modified -eq 0 ] && [ $length_renamed -eq 0 ] && [ $length_deleted -eq 0 ]
        then
            echo "No Changes at all.  No Need to Commit"
            exit
        fi
        if [[ $flags == "-y" ]]
        then
            answer="yes"
        else
            echo -e "\nCommit Changes?  (Yes/No)"
            read -e answer
        fi
        case "$answer" in
            [yY] | [yY][Ee][Ss])
                echo "Comments?  ENTER THEM NOW!!!";
                read -e comments;
                if [ "$comments" == "" ]
                then
                    echo "Cannot commit without comments, ya turkey!!!"
                    git reset HEAD
                    exit 0
                fi
                git commit -m "$comments";
                git push;
                exit 0;;
            [nN] | [nN][oO])
                git reset HEAD;
                exit 0;;
            *)
                echo Invalid option selected;
                git reset HEAD;;
        esac
    }

    #-------------------------------------------------------------------------------
    #  Main Function (calls err-body else)
    #-------------------------------------------------------------------------------
    main(){
    gitLists
    gitStage
    git pull
    gitGo
    }

#-------------------------------------------------------------------------------
#  Kick this pig
#-------------------------------------------------------------------------------
isGit

I'll be the first to admit that this has (in one way or another) already been done, and probably better too, but I wanted to create my own. I'm sure I'll keep adding to it, polishing it, and making sure I've accounted for most (if not all) edge cases or errors, and of course all the while using Git to keep track of the changes.