Skip to content

Instantly share code, notes, and snippets.

@rzwitserloot
Last active September 25, 2015 18:28
Show Gist options
  • Save rzwitserloot/964945 to your computer and use it in GitHub Desktop.
Save rzwitserloot/964945 to your computer and use it in GitHub Desktop.
grb-like git frontend that does all grb does and more (specifically: all-work-in-branches model)
#!/bin/bash
#
# Copyright © 2009-2013 Reinier Zwitserloot and Roel Spilker.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
ORIGIN=origin
MASTER=master
EXPLAIN=no
OFFLINE=no
if [ "$1" = "explain" ]; then
EXPLAIN=yes
shift
fi
if [ "$1" = "-o" ]; then
OFFLINE=yes
shift
fi
if [ "$1" = "--offline" ]; then
OFFLINE=yes
shift
fi
if [ "$1" = "explain" ]; then
EXPLAIN=yes
shift
fi
runCmd() {
if [ "$EXPLAIN" = "yes" ]; then
echo $*
else
$* || exit 1
fi
}
gitPull() {
if [ "$OFFLINE" != "yes" ]; then
runCmd git fetch --prune
runCmd git merge $ORIGIN/$MASTER
else
echo "WARNING: Skipping 'git pull' due to offline mode."
fi
}
cmdLineHelp() {
echo "start Create a new local branch after updating master."
echo "rename renames a local branch."
echo "publish promotes a local branch (uploads to remote so others can track it), and then tracks it."
echo "track creates a new local branch that tracks the given remote branch."
echo "join upgrades $MASTER to include the local branch via rebase so the history does not show a merge, then deletes the branch."
echo "merge upgrades $MASTER to include the named branch via merge so history does show the merge, then deletes the branch."
echo "update refreshes $MASTER then rebases local branch on top of any changes."
echo
echo "A command may be prefixed with 'explain' to print the git commands that it'll run."
echo "A command may be prefixed with '-o' to avoid things that require an internet connection (push and pull)."
echo "Where a local branch name is omitted, the branch you're currently in is used."
echo "the main branch is assumed to be '$MASTER' and the head remote is assumed to be called '$ORIGIN'."
}
LOCALNAME=$2
CUR_BRANCH="$(git symbolic-ref HEAD 2>/dev/null)"
CUR_BRANCH="${CUR_BRANCH##refs/heads/}"
getBranchName() {
if [ "$LOCALNAME" = "" ]; then
if [ "$CUR_BRANCH" = "" ]; then
echo "Missing branch name and you're not in a branch right now."
exit 1
fi
if [ "$CUR_BRANCH" = "$MASTER" ]; then
echo "Missing branch name and you're in $MASTER right now."
exit 1
fi
LOCALNAME=$CUR_BRANCH
fi
}
getLocalBranchName() {
getBranchName
if git branch -r | grep "$ORIGIN/$LOCALNAME$" > /dev/null; then
echo "Branch $CUR_BRANCH isn't local."
exit 1
fi
}
switchTo() {
if [ "$1" != "$CUR_BRANCH" ]; then
runCmd git checkout "$1"
fi
}
if [ "$1" = "" ]; then
cmdLineHelp
exit 0
fi
if [ "$1" = "start" ]; then
if [ "$2" = "" ]; then
echo "Syntax: gitc start branchName"
exit 1
fi
switchTo $MASTER
gitPull
runCmd git checkout -b "$2"
exit 0
fi
if [ "$1" = "rename" ]; then
NEWNAME="$3"
if [ "$3" = "" ]; then
LOCALNAME=""
NEWNAME="$2"
fi
if [ "$NEWNAME" = "" ]; then
echo "Syntax: gitc rename newName to rename current branch, or gitc rename oldName newName."
exit 1
fi
getLocalBranchName
runCmd git branch -m "$LOCALNAME" "$NEWNAME"
exit 0
fi
if [ "$1" = "publish" ]; then
if [ "$OFFLINE" = "yes" ]; then
echo "ERROR: 'publish' not possible in offline mode."
fi
getLocalBranchName
echo "Should I try to rebase $LOCALNAME first? (y/n)"
read REBASEFIRST
if [ "$REBASEFIRST" = "y" ]; then
switchTo $MASTER
gitPull
runCmd git checkout $LOCALNAME
runCmd git rebase $MASTER
CUR_BRANCH=$LOCALNAME
elif [ "$REBASEFIRST" = "n" ]; then
echo Skipping Rebase
else
echo "Only 'y' or 'n' are valid answers."
exit 1
fi
runCmd git push $ORIGIN $LOCALNAME:refs/heads/$LOCALNAME
runCmd git fetch $ORIGIN
runCmd git config branch.$LOCALNAME.remote $ORIGIN
runCmd git config branch.$LOCALNAME.merge refs/heads/$LOCALNAME
switchTo $LOCALNAME
exit 0
fi
if [ "$1" = "track" ]; then
TRNAME="$2"
if [ "$TRNAME" = "" ]; then
echo "Syntax: gitc track remoteBranchName"
exit 1
fi
if [ "$OFFLINE" != "yes" ]; then
runCmd git fetch $ORIGIN
fi
runCmd git branch --track $TRNAME $ORIGIN/$TRNAME
runCmd git checkout $TRNAME
exit 0
fi
if [ "$1" = "update" ]; then
getLocalBranchName
switchTo $MASTER
gitPull
runCmd git checkout $LOCALNAME
runCmd git rebase $MASTER
exit 0
fi
if [ "$1" = "join" ]; then
if [ "$OFFLINE" = "yes" ]; then
echo "ERROR: 'join' not possible in offline mode."
fi
getLocalBranchName
switchTo $MASTER
gitPull
runCmd git checkout $LOCALNAME
runCmd git rebase $MASTER
runCmd git checkout $MASTER
runCmd git merge $LOCALNAME
runCmd git branch -d $LOCALNAME
runCmd git push
exit 0
fi
if [ "$1" = "merge" ]; then
if [ "$OFFLINE" = "yes" ]; then
echo "ERROR: 'join' not possible in offline mode."
fi
getBranchName
switchTo $MASTER
gitPull
runCmd git merge $LOCALNAME
runCmd git push
runCmd git branch -d $LOCALNAME
if git branch -r | grep "$ORIGIN/$LOCALNAME" > /dev/null; then
runCmd git push $ORIGIN :refs/heads/$LOCALNAME
fi
exit 0
fi
echo Unknown command: $1 - rerun this script with no arguments to see available commands.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment