Skip to content

Instantly share code, notes, and snippets.

@rpavlik
Created January 11, 2012 20:25
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 rpavlik/1596589 to your computer and use it in GitHub Desktop.
Save rpavlik/1596589 to your computer and use it in GitHub Desktop.
Script for moving branches from one git-svn mirror to a new one
#!/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment