Skip to content

Instantly share code, notes, and snippets.

@inhies
Last active November 18, 2016 21:15
Show Gist options
  • Save inhies/7635032 to your computer and use it in GitHub Desktop.
Save inhies/7635032 to your computer and use it in GitHub Desktop.
Subtree is a helper utility for working with git subtrees. Easily add, update, and remove subtrees from your git repo.
#!/bin/bash
# subtree -- a utility to help working with git subtree's
# creator: inhies
# 24 November 2013
version=1.1.1
function usage() {
case "$1" in
"")
echo "Usage: subtree <add | update | rm>"
;;
"add")
echo "Usage: subtree add <remote name> <git url> <branch> <prefix>"
;;
"update")
echo "Usage: subtree update <prefix | 'all'>"
;;
"rm")
echo "Usage subtree rm <prefix>"
;;
esac
exit 1
}
# Check if we are in the root of a git repository.
isGit=$(git rev-parse --git-dir 2> /dev/null)
if [ ! -d .git ]; then
if [ "$isGit" == "" ]; then
# Check for a blank response, indicating a non-existant git repository.
echo "subtree: You are not within a git repository"
exit 1
else
# We are in a git repository, but not in the root of it, where we need to be.
echo "subtree: Subtree must be ran from within the git root directory, `dirname $isGit`"
exit 1
fi
exit
else
if [ "$isGit" != ".git" ]; then
# A .git folder exists in this directory, but git says we aren't actually in a repository.
echo "subtree: A .git directory exists, but this doesnt seem to be a valid git repository"
exit 1
fi
fi;
declare -A rawMap # Global associative array to hold raw .subtrees lines
# Load the subtrees file in to the map.
function loadSubtrees(){
while read line
do
temparray=( $line )
rawMap[${temparray[0]}]=$line
done < "./.subtrees"
}
function add() {
# Add the remote and return if there is an error
git remote add -f $1 $2
if [ "$?" -ne "0" ]; then
return
fi
git subtree add --prefix $4 $1 $3 --squash
# If there was an error adding the subtree, remove the remote we just added
if [ "$?" -ne "0" ]; then
git remote rm $1
return
fi
echo "$1 $2 $3 $4" >> .subtrees
git add .subtrees
git commit -m "Update .subtrees for $1"
}
# name prefix
function remove() {
echo "subtree: Removing remote $1"
git remote rm $1
if [ "$?" -ne "0" ]; then
echo "subtree: Erorr removing remote $1"
return
fi
echo "subtree: Removing files from $4"
rm -rf ./$4
if [ "$?" -ne "0" ]; then
echo "subtree: Erorr removing files from $4"
return
fi
git rm -r $4
if [ "$?" -ne "0" ]; then
echo "subtree: Erorr removing files '$4' from git"
return
fi
echo "subtree: Removing $1 from .subtrees file"
PREFIX=$(echo "go/.vim/bundle/gocode" | sed -e 's/[\/&]/\\&/g')
sed -i".bak" "/$PREFIX/d" .subtrees
if [ "$?" -ne "0" ]; then
echo "subtree: Erorr removing subtree $1 from .subtrees file"
return
fi
echo "subtree: old .subtrees file has been copied to .subtrees.bak"
git add .subtrees
git commit -m "Removed subtree $1 from '$4'"
if [ "$?" -ne "0" ]; then
echo "subtree: Erorr commiting removal of subtree $1"
return
fi
}
function update(){
git fetch $1 $3
if [ "$?" -ne "0" ]; then
return
fi
git subtree pull --prefix $4 $1 $3 --squash
}
case "$1" in
"-v" | "--version")
echo "subtree version $version"
exit 0
;;
"update")
loadSubtrees
case "$2" in
"all")
for v in "${rawMap[@]}"; do
update $v
if [ "$?" -ne "0" ]; then
echo "subtree: error updating subtree:\n\t$v"
exit 1
fi
done
;;
*)
if [ "$2" == '' ]; then
usage "update"
fi
if [ "${rawMap[$2]}" == "" ] ; then
echo "subtree: $2 is not a subtree item. Check .subtrees file"
exit 1
fi
update ${rawMap[$2]}
if [ "$?" -ne "0" ]; then
echo "subtree: error updating subtree $2"
exit 1
fi
;;
esac
;;
"add")
loadSubtrees
if [ "${rawMap[$2]}" != "" ] ; then
echo "subtree: $2 already exists"
exit 1
fi
if [ "$5" == '' ]; then
usage "add"
fi
add $2 $3 $4 $5
if [ "$?" -ne "0" ]; then
echo "subtree: error adding subtree $2"
exit 1
fi
;;
"rm" | "remove")
if [ "$2" == '' ]; then
usage "rm"
fi
loadSubtrees
if [ "${rawMap[$2]}" == "" ] ; then
echo "subtree: $2 is not a subtree item. Check .subtrees file"
exit 1
fi
remove ${rawMap[$2]}
if [ "$?" -ne "0" ]; then
echo "subtree: error removing subtree $2"
exit 1
fi
;;
*)
usage
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment