Skip to content

Instantly share code, notes, and snippets.

@leeor
Last active August 29, 2015 14:20
Show Gist options
  • Save leeor/bc806b40192c24c4fea0 to your computer and use it in GitHub Desktop.
Save leeor/bc806b40192c24c4fea0 to your computer and use it in GitHub Desktop.
basic multi-module flow management a-la gitflow
#!/bin/bash
# gist-id bc806b40192c24c4fea0
set -e
set -o pipefail
# unified branching
# unified checkout
# cross-repo status
# actions that may result in merge conflicts are not being automated
USER="leeor"
REMOTE="origin"
MASTER_BRANCH="master"
FEATURE_PREFIX="feature"
DEVELOP_BRANCH="${USER}/develop"
DRYRUN=0
if [[ $1 == "-n" || $1 == "--dry-run" ]]; then
DRYRUN=1; shift
fi
COMMAND=$1; shift
colors=(31 32 33 34 35 36 37)
count=0
while [[ ${colors[count]} != "" ]]; do
count=$(( $count + 1 ))
done
n=0
set -o nounset
function runcmd {
if [[ $DRYRUN == 0 ]]; then
eval $@ | sed "s#^#${PREFIX}[${color}m${repo}:${PREFIX}[0m #"
else
echo $@ | sed "s#^#${PREFIX}[${color}m${repo}:${PREFIX}[0m #"
fi
}
function do_prune {
for remote in $(git -C $1 remote); do
runcmd "git -C $1 remote prune $remote 2>&1"
done
}
for repo in `cat .repos`; do
let "ci = $n % $count" || true
n=$(( $n + 1 ))
color=${colors[ci]}
PREFIX=$'\033'
case $COMMAND in
status)
runcmd "git -C $repo status --porcelain --untracked=no --ignore-submodules $@ 2>&1"
;;
untracked)
runcmd "git -C $repo status --porcelain --untracked=normal --ignore-submodules $@ 2>&1"
;;
branch)
runcmd "git -C $repo branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'"
;;
checkout)
runcmd "git -C $repo checkout $@ 2>&1"
;;
update)
runcmd "git -C $repo remote update $@ 2>&1"
;;
prune)
do_prune $repo
;;
rebase)
runcmd "git -C $repo rebase $@ 2>&1"
;;
feature)
[[ -z "${SUBCOMMAND:-}" ]] && SUBCOMMAND=$1 && shift
[[ -z "${FEATURE_NAME:-}" ]] && FEATURE_NAME=$1 && shift
[[ -z "${FEATURE_BRANCH:-}" ]] && FEATURE_BRANCH="${USER}/${FEATURE_PREFIX}/${FEATURE_NAME}"
# run prune before checking for branch existence
do_prune $repo
FEATURE_BRANCH_EXISTS=0
if git -C $repo branch --no-color 2>&1 | sed 's/^[* ]*//' | grep $FEATURE_BRANCH > /dev/null; then
FEATURE_BRANCH_EXISTS=1
fi
REMOTE_FEATURE_BRANCH_EXISTS=0
if git -C $repo branch -r --no-color 2>&1 | sed 's/^[* ]*//' | grep "$REMOTE/$FEATURE_BRANCH" > /dev/null; then
REMOTE_FEATURE_BRANCH_EXISTS=1
fi
CURRENT_BRANCH=$(git -C $repo branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
case $SUBCOMMAND in
start)
if [[ $FEATURE_BRANCH_EXISTS == 0 ]]; then
if [[ $REMOTE_FEATURE_BRANCH_EXISTS == 0 ]]; then
if [[ $CURRENT_BRANCH != $DEVELOP_BRANCH ]]; then
echo "Need to have the develop branch checked out to start a new feature"
exit 1
fi
runcmd "git -C $repo checkout -b $FEATURE_BRANCH 2>&1"
runcmd "git -C $repo push -u 2>&1"
else
runcmd "git -C $repo checkout -t $REMOTE/$FEATURE_BRANCH 2>&1"
fi
else
runcmd echo "Feature branch ${FEATURE_BRANCH} already exists"
fi
;;
finish)
if [[ $FEATURE_BRANCH_EXISTS == 1 ]]; then
if [[ $CURRENT_BRANCH == $FEATURE_BRANCH ]]; then
runcmd "git -C $repo checkout $MASTER_BRANCH 2>&1"
fi
if [[ $REMOTE_FEATURE_BRANCH_EXISTS == 1 ]]; then
# delete local branch
runcmd "git -C $repo branch -d $FEATURE_BRANCH 2>&1"
# and remote branch
runcmd "git -C $repo push --delete $REMOTE $FEATURE_BRANCH 2>&1"
else
# since there's no longer a remote branch, be willing to
# delete even branches that are not fully merged
runcmd "git -C $repo branch -D $FEATURE_BRANCH 2>&1"
fi
else
runcmd echo "Feature branch ${FEATURE_BRANCH} was not found"
fi
;;
esac
;;
exec)
runcmd "git -C $repo $@"
;;
esac
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment