--- /dev/null
+#!/bin/bash
+#
+# Moves a branch to or from the current git tree to or from
+# another git tree
+#
+# usage: git-branchmove get|put REMOTE BRANCH
+
+set -e
+set -o posix
+
+fail () { echo >&2 "git-branchmove: $*"; exit 16; }
+badusage () { fail "bad usage: $*"; }
+
+case "$#.$1" in
+3.get)
+ op=get
+ remote="$2"
+ branch="$3"
+ ;;
+3.put)
+ op=put
+ branch="$3"
+ ;;
+*)
+ badusage "wrong number of arguments or wrong operation"
+ ;;
+esac
+
+# Plan of attack:
+# determine execute-sh runes for src and dst trees
+# check that source branch is not checked out
+# list affected branches on source
+# list affected branches on destination and moan if any nonequal overlap
+# transfer src->dst refs/heads/BRANCH:refs/heads/BRANCH
+# transfer and merge reflog(s) xxx todo
+# delete src refs
+
+case "$remote" in
+*:*) remoteurl="$remote" ;;
+*) remoteurl="$(
+ git config remote."$remote".pushurl ||
+ git config remote."$remote".url ||
+ fail "no pushurl or url defined for remote $remote"
+ )"
+esac
+
+remote_spec="$(perl -e '
+ $_ = $ARGV[0];
+ if (m#^ssh://([^:/]+)(?:\:(\w+))?#) {
+ print "$'\''|ssh ";
+ print " -p $3" if $2;
+ print "$1\n";
+ } elsif (m#^([-+_.0-9a-zA-Z\@]+):(?!//)#) {
+ print "$'\''|ssh $1\n";
+ } else {
+ die "git-branchmove: unsupported remote url \`$_'\''\n";
+ }
+' "$remoteurl")"
+
+remote_path="${remote_spec%%|*}"
+remote_rune="${remote_spec#*|}"
+
+case $op in
+get)
+ src_rune="$remote_rune"
+ src_path="$remote_path"
+ dst_rune="sh -c"
+ dst_path=.
+ ;;
+put)
+ dst_rune="$remote_rune"
+ dst_path="$remote_path"
+ src_rune="sh -c"
+ src_path=.
+ ;;
+esac
+