Skip to content

Instantly share code, notes, and snippets.

@z0u
Forked from neowulf/git-svn-diff.sh
Created February 4, 2012 22:43
Show Gist options
  • Save z0u/1740799 to your computer and use it in GitHub Desktop.
Save z0u/1740799 to your computer and use it in GitHub Desktop.
Creates a patch file between svn branch and git branch
#!/bin/bash
#
# git-svn-diff originally by (http://mojodna.net/2009/02/24/my-work-git-workflow.html)
# modified by mike@mikepearce.net
# modified by aconway@[redacted] - handle diffs that introduce new files
# modified by t.broyer@ltgt.net - fixes diffs that introduce new files
# modified by m@rkj.me - fix sed syntax issue in OS X
# modified by alex@phatcore.com - search for last SVN commit; allow diff
# against non-tracking branch; remove function names on @@ lines.
#
# SYNOPSIS
# git-svn-diff.sh [commit]
#
# Generate an SVN-compatible diff. If no arguments are provided, the diff will
# be against the most recent SVN revision on this branch. Otherwise, the diff
# will be against the specified commit (or branch). This is handy in the
# situation where you have a local base branch containing commits that will
# never be pushed to SVN, like so:
#
# ---A---B---C origin/master or remotes/git-svn
# \ \
# D---E---F master
# \
# G---H---I feature
#
# In this case, use `git checkout feature; git-svn-diff.sh master`. The patch
# will apply against commit B (and will be annotated with the SVN revision of
# B), but won't include D, E and F. After committing the patch to SVN, merge
# the remote into master and forget the feature branch.
#
# ---A---B---C---I' origin/master or remotes/git-svn
# \ \ \
# D---E---F---I" master
# \
# G---H---I (deleted)
#
convert-to-svn-rev() {
echo -n "Searching for SVN revision" >&2
while read rev; do
echo -n . >&2
svnRev=$(git svn find-rev $rev)
if [ "x$svnRev" != x ]; then
echo >&2
echo "git:$rev svn:$svnRev" >&2
echo $rev $svnRev
break
fi
done
}
# Walk through commits in reverse date order, looking for the most recent
# commit that came from SVN. The SVN revision of that commit is returned.
find-svn-rev() {
git rev-list --date-order --max-count=200 HEAD | convert-to-svn-rev
}
# Get the highest revision number
REVS=( $(find-svn-rev) )
GITREV=${REVS[0]}
SVNREV=${REVS[1]}
if [ $# -gt 0 ]; then
REF=$*
else
REF=$GITREV
fi
# Then do the diff from the highest revision on the current branch
# and masssage into SVN format
git diff --no-prefix $REF |
sed -e "/--- \/dev\/null/{ N; s|^--- /dev/null\n+++ \(.*\)|--- \1 (revision 0)\n+++ \1 (revision 0)|;}" \
-e "s/^--- .*/& (revision $SVNREV)/" \
-e "s/^+++ .*/& (working copy)/" \
-e "s/^diff --git [^[:space:]]*/Index:/" \
-e "s/^\(@@ .* .* @@\).*/\1/" \
-e "s/^index.*/===================================================================/"
@z0u
Copy link
Author

z0u commented Feb 4, 2012

This version works even when not using git-svn, e.g. when the remote repository is a clone of an SVN repository (instead of the remote actually being an SVN repository). The script does not use the tip of the tracking branch to get the SVN revision; instead, it searches for the most recent commit that was sourced from SVN. Also, this version allows making a diff against a branch other than the tracking branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment