public
Created

Script for moving branches from one git-svn mirror to a new one

  • Download Gist
portbranch.sh
Shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
#!/bin/bash
# Call like ./portbranch official-upstream/3.0 my-3.0-fixes
 
# Original Author:
# 2012 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2012.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
 
USAGE="<newupstreambranch> [<yourbranch>]"
LONG_USAGE=$(cat <<EOS
Port a branch between two different git-svn imports of the same original
repository.
 
If a branch is not specified, the current branch is used.
EOS
)
 
# Setup git stuff
. "$(git --exec-path)/git-sh-setup"
 
if [ "$1" == "-h" ]; then
usage
fi
 
require_work_tree
require_clean_work_tree portbranch "Please commit them - stashes would be left behind."
 
YOUR_REMOTE=origin
 
function verifyLocalBranch() {
branchname=$1
git show-ref --verify --quiet "refs/heads/${branchname}" || git branch "${branchname}" "${YOUR_REMOTE}/${branchname}"
}
 
function getCommitSubject() {
git log --pretty=format:'%s' -n 1 $1
}
 
upstream_branch=$1
your_branch=$2
 
# Simultaneously check for detached head and fill in your_branch if you only
# passed one argument
if current_branch=$(git symbolic-ref -q HEAD); then
case "$#" in
1)
your_branch="${current_branch}"
;;
esac
else
die "You're currently on a detached head!"
fi
 
verifyLocalBranch "${your_branch}"
 
# Step 1: Find the latest commit on ${your_branch} that was from git-svn
if parenthash=$(git log --fixed-strings --grep="git-svn-id:" --pretty=format:"%H" -n 1 "${your_branch}"); then
# The following grabs, from the commit message body's line that includes git-svn-id,
# the last two fields (a sort of SVN URL and an apparent GUID), then strips off
# everything up to and including the domain name to use as a unique ID for that commit.
# The domain removal is so that anonymous vs. logged-in svn repos should hopefully be OK -
# it's just a heuristic that works for Google Code.
parentsvnid=$(git log ${parenthash} -n 1 --pretty=format:"%b" | grep "git-svn-id" | cut --delimiter=" " -f 2-3 | sed 's_[^/]*//[^/]*__')
else
die "No commits in this branch have a git-svn-id listed in their commit messsage!"
fi
 
# Step 2: Find the matching commit
 
if ontohash=$(git log --fixed-strings --grep="${parentsvnid}" --pretty=format:"%H" "${upstream_branch}" -n 1); then
# we got one, I think! Now just make sure there are no common ancestors...
if git merge-base ${parenthash} ${ontohash} > /dev/null; then
die "Apparent branch-point ${parenthash} and located matching commit ${ontohash} have a common ancestor!"
fi
else
die "Could not find a match for branch point commit ${parenthash}"
fi
 
 
#Step 3: Perform the rebase to transplant ${your_branch}
 
say "Old parent commit:"
GIT_PAGER=cat git log -n 1 -s ${parenthash}
 
say
say "New parent commit:"
GIT_PAGER=cat git log -n 1 -s ${ontohash}
 
say
say "The command we are about to run is:"
say " git rebase --onto=${ontohash} ${parenthash} ${your_branch}"
say "From here on out, it's up to git rebase - this script is done."
say "Continue? [yn]"
 
read CONFIRM
if [ "${CONFIRM}" == "y" ]; then
exec git rebase --onto=${ontohash} ${parenthash} ${your_branch}
else
say "Didn't get 'y', exiting without rebasing."
fi

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.