#!/bin/bash # I'm writing this in BASH because I hate myself, apparently. list_branches() { git for-each-ref refs/heads --format="%(refname:short)" } list_remote_branches() { git for-each-ref refs/heads --format="%(refname:short)" } case "$1" in "") echo 'TODO: Display help, or git status if inside a repo' ;; stage) if [ -z "$2" ]; then echo Staging all modified files git add -u :/ else echo Staging "${@:2}" git add "${@:2}" fi ;; unstage) echo Unstaging if [ -z "$2" ]; then echo The stage has been reset. git reset HEAD else git reset HEAD "${@:2}" fi ;; reset) echo Resetting if [ -z "$2" ]; then echo The working directory has been reset. git checkout -f HEAD else git checkout "${@:2}" fi ;; commit) echo Committing if [ -z "$2" ]; then read -p 'Message: ' msg git commit -m "$msg" else git commit -m "$2" fi ;; branch) echo 'Switching to branch' if [ -z "$2" ]; then echo '! Specify branch name' else git stash # Save branch index state if git rev-parse --verify --quiet "$2" > /dev/null; then git checkout "$2" else git checkout -b "$2" fi git stash pop # Restore branch index state fi ;; rmbranch) echo 'Delete branch' if [ -z "$2" ]; then echo '! Specify branch name' else git branch -d "$2" fi ;; fetch) echo Updating if [ -z "$2" ]; then git fetch --all branches="$(list_branches)" else branches = "${@:2}" git fetch "$branches" fi # Fast-forward local branches. I owe a lot to http://stackoverflow.com/a/24451300/2168416 current_branch=$(git rev-parse --abbrev-ref HEAD) for local_branch in $branches; do remote=$(git config --get branch.$local_branch.remote) remote_branch=$(git config --get branch.$local_branch.merge | sed 's:refs/heads/::') # Git throws an error if we try the fetch command on the current branch. Sheesh if [ "$current_branch" = "$local_branch" ]; then git merge --ff-only $remote/$remote_branch else git fetch $remote $remote_branch:$local_branch fi done ;; ignore) ;; status) # TODO: figure out how to git config --global color.status always automatically. git status \ | grep -v '# On branch' \ | grep -v '# (use "git push" to publish your local commits)' \ | grep -v '# (use "git reset HEAD ..." to unstage)' \ | grep -v '# (use "git add ..." to update what will be committed)' \ | grep -v '# (use "git checkout -- ..." to discard changes in working directory)' \ | grep -v '# (use "git add ..." to include in what will be committed)' \ | grep -v 'nothing added to commit but untracked files present (use "git add" to track)' ;; diff) if [ -z "$2" ]; then echo 'Compare working tree with HEAD' git diff HEAD else if [ -z "$3" ]; then if [ "$2" = 'STAGE' ]; then echo 'Compare working tree with stage' git diff else echo "Compare working tree with $2" git diff "$2" fi else if [ "$2" = 'STAGE' ]; then echo "Compare stage with $3" git diff --cached "$3" else echo "Compare $2 with $3" git diff "$2" "$3" fi fi fi ;; review) echo 'Compare stage with HEAD' git diff --cached HEAD ;; push) echo 'Pushing' # Check to see if upstream is set. if git rev-parse --abbrev-ref @{upstream} >/dev/null ; then git push else # Get local branch name local_branch=$(git rev-parse --abbrev-ref HEAD) # Check for multiple remotes remote_count=$(git remote show | wc -l) remotes=$(git remote show | tr '\n' ' ' | sed 's/\s*$//g') if [ "$remote_count" = "1" ]; then # If only one remote remote="$remotes" else read -p "Which remote to push? (${remotes}): " remote fi read -p "Choose name for branch on '${remote}' [${local_branch}]: " remote_branch if [ "$remote_branch" = "" ]; then remote_branch="$local_branch" fi echo "I will run git push --set-upstream ${remote} ${remote_branch}" git push --set-upstream ${remote} ${remote_branch} fi ;; esac