Skip to content

Instantly share code, notes, and snippets.

@cb372
Last active December 26, 2015 00:39
Show Gist options
  • Save cb372/7065620 to your computer and use it in GitHub Desktop.
Save cb372/7065620 to your computer and use it in GitHub Desktop.
Utility method to checkout a given git branch or tag. Useful in deployment scripts. Requires git 1.8.x.
#!/bin/bash
# Checkout the given branch or tag to the given directory.
# Clones the repo if a clone does not already exist.
#
# Arguments:
# $1 = Git repo URL e.g. #git@github.com:foo/bar.git" (Mandatory)
# $2 = Local directory e.g. /tmp/checkout" (Mandatory, must be absolute path)
# $3 = Branch or tag name e.g. "develop" or "0.1" (Mandatory)
function git_checkout {
if [ $# -lt 3 ]; then
echo "Error: Not enough arguments supplied."
echo "Usage: git_checkout <git URL> <local dir> <branch or tag>"
return 1
fi
local git_url=$1
local checkout_dir=$2
local branch_or_tag=$3
# Save env vars so we can clean up after ourselves
if [ -n "${GIT_WORK_TREE+set}" ]; then local save_git_work_tree=$GIT_WORK_TREE; fi
if [ -n "${GIT_DIR+set}" ]; then local save_git_dir=$GIT_DIR; fi
if [ -e $checkout_dir ]; then
echo "Found existing clone of [$git_url] at [$checkout_dir]."
echo
export GIT_WORK_TREE=$checkout_dir
export GIT_DIR=$GIT_WORK_TREE/.git
echo "Fetching latest branches and tags from origin."
git --no-pager fetch origin
echo
local previous_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$previous_branch" != "HEAD" ]; then
echo "Currently checked out branch: [$previous_branch]"
else
# We are probably in detached HEAD state,
# most likely because we checked out a tag
echo "Currently checked out tag: [$(git describe --always --tags)]"
fi
echo "HEAD:"
echo "-----"
git --no-pager log -1
echo "-----"
echo
local previous_head=$(git rev-list --max-count=1 HEAD --)
echo "Checking out [$branch_or_tag] ..."
git --no-pager checkout -q $branch_or_tag
echo
echo "Pulling latest changes from origin..."
git --no-pager pull origin $branch_or_tag
echo
echo "The following files have been updated."
diff_cmd="git --no-pager diff --stat $previous_head HEAD"
echo "-----"
$diff_cmd
echo "-----"
echo
echo "New HEAD:"
echo "-----"
git --no-pager log -1
echo "-----"
echo
else
echo "Cloning [$git_url] to [$checkout_dir]..."
git --no-pager clone $git_url $checkout_dir
echo
# Don't set env vars until after clone, as it causes git to go crazy
# and put the .git folder contents into the working tree
export GIT_WORK_TREE=$checkout_dir
export GIT_DIR=$GIT_WORK_TREE/.git
echo "Checking out [$branch_or_tag] ..."
git --no-pager checkout -q $branch_or_tag
echo
fi
# Clean up env vars
if [ -n "${save_git_work_tree+set}" ]; then export GIT_WORK_TREE=$save_git_work_tree; else unset GIT_WORK_TREE; fi
if [ -n "${save_git_dir+set}" ]; then export GIT_DIR=$save_git_dir; else unset GIT_DIR; fi
echo "Done!"
return 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment