GNU/Linux xterm-256color bash 4 views

~/.local/bin/git-close-bubble

#!/usr/bin/env bash
# Close a merge bubble started with a "BEGIN ..." commit.
# Usage: git close-bubble <message> [BEGIN-commit]
#        git close-bubble --dry-run [BEGIN-commit]

set -euo pipefail

DRY_RUN=0
if [ "${1:-}" = "--dry-run" ]; then
    DRY_RUN=1
    shift
fi

if [ "$DRY_RUN" -eq 0 ] && [ $# -lt 1 ]; then
    echo "usage: git close-bubble <message> [BEGIN-commit]" >&2
    echo "       git close-bubble --dry-run [BEGIN-commit]" >&2
    exit 1
fi

if [ "$DRY_RUN" -eq 1 ]; then
    MSG=""
    BEGIN_ARG="${1:-}"
else
    MSG="$1"
    BEGIN_ARG="${2:-}"
fi

B=$(git branch --show-current)

if [ -n "$BEGIN_ARG" ]; then
    S=$(git rev-parse --verify "$BEGIN_ARG")
else
    CLOSED=$(git log --merges --format='%P' | awk '{print $1}' | sort -u)
    S=""
    while IFS= read -r c; do
        if ! printf '%s\n' "$CLOSED" | grep -qx "$c"; then
            S="$c"; break
        fi
    done < <(git log --grep='^BEGIN ' --format='%H')
    if [ -z "$S" ]; then
        echo "error: no unclosed BEGIN commit found" >&2
        exit 1
    fi
fi

echo "Would close bubble starting at: $(git log -1 --format='%h %s' "$S")"

if [ "$DRY_RUN" -eq 1 ]; then
    echo "(dry-run; no changes made)"
    exit 0
fi

git checkout "$S"
git merge --no-ff "$B" -m "$MSG"
M=$(git rev-parse HEAD)
git checkout "$B"
git merge "$M"

echo "Done. Branch '$B' now points at $M. Inspect, then 'git push' when satisfied."

More recordings by thunderrabbit

git close-bubble 0:39

by thunderrabbit