Skip to content

Instantly share code, notes, and snippets.

@mislav
Last active January 3, 2016 21:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mislav/8519483 to your computer and use it in GitHub Desktop.
Save mislav/8519483 to your computer and use it in GitHub Desktop.
My branches + CI workflow. Requires hub for the `hub ci-status` command
#!/bin/sh
# Usage: git promote [<remote>[/<branch>]]
#
# Pushes the current branch to remote.
set -e
branch="$(git symbolic-ref --short HEAD)"
remote="${1%/*}"
remote_branch="${1#*/}"
[ "$remote_branch" != "$remote" ] || remote_branch="$branch"
if [ -z "$remote" ]; then
remote="$(git remote -v | grep -E '(git@|https://)github' | head -1 | awk '{print $1}')"
fi
if [ -z "$remote" ]; then
echo "no remote with write access" >&2
exit 1
fi
git push -u "$remote" "$branch":"${remote_branch}"
#!/usr/bin/env bash
# Usage: merge [<BRANCH>]
#
# Sophisticated git merge with integrated CI check and automatic cleanup upon
# completion.
#
# - Fast-forwards BRANCH to latest version (if applicable)
# - Checks if BRANCH passed CI
# - Fast-forwards master to latest version
# - Merges BRANCH into master
# - Pushes master upstream
# - Deletes BRANCH both locally and on its remote.
#
# Depends on: hub v1.10.6
set -e
branch="$1"
upstream_name=origin
upstream_branch=""
if [ -z "$branch" ]; then
branch="$(git symbolic-ref -q HEAD)"
branch="${branch#refs/heads/}"
fi
symbolic_full_name() {
local output
if output="$(git rev-parse --symbolic-full-name "$@" 2>/dev/null)"; then
echo "${output#refs/remotes/}"
else
return 1
fi
}
checkout_latest() {
git checkout -q "$1" && git pull --ff-only
}
if master_name="$(symbolic_full_name "$upstream_name")"; then
master_name="${master_name#*/}"
else
master_name=master
fi
if [ "$branch" = "$master_name" ]; then
echo "Won't merge master branch into itself!" >&2
exit 1
fi
if upstream="$(symbolic_full_name "${branch}@{u}")"; then
upstream_remote="${upstream%%/*}"
upstream_branch="${upstream#*/}"
fi
if [ -n "$upstream_branch" ]; then
checkout_latest "$branch"
fi
if ! output="$(hub ci-status "$branch" 2>&1)"; then
echo "hub ci-status: $output" >&2
exit 1
fi
checkout_latest "$master_name"
git merge --no-ff "$branch" -m "Merge branch '${upstream_branch:-$branch}'"
git push "$upstream_name" "$master_name"
git branch -d "$branch"
if [ -n "$upstream_branch" ]; then
git branch -dr "${upstream_remote}/${upstream_branch}"
git push "$upstream_remote" --delete "$upstream_branch"
fi
#!/usr/bin/env bash
# Usage: see git-promote
#
# Pushes the current branch to remote and opens a tiny tmux split to track
# the CI status. Upon completion, speaks the status aloud using `say`.
set -e
if [ "$1" != "--wait" ]; then
git promote "$@"
tmux split-window -dv -l 2 "'$0' --wait"
else
rev="$(git rev-parse -q HEAD)"
branch="$(git symbolic-ref -q HEAD)"
while true; do
sleep 10
STATUS=0
output="$(hub ci-status "$rev" 2>&1)" || STATUS="$?"
if [ "$STATUS" -eq 2 ]; then
printf '*'
elif [ "$STATUS" -eq 3 ]; then
printf '.'
else
echo " $output"
say -v fred "${branch#refs/heads/} is $output"
exit "$STATUS"
fi
done
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment