From bb79169c4eba10c11cff5317a50bc3aa41f8526b Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Wed, 9 Nov 2011 10:49:25 -0600 Subject: add nothingmuch's git-svn-abandon scripts --- bin/git/git-svn-abandon-cleanup | 16 ++++++++++ bin/git/git-svn-abandon-fix-refs | 63 ++++++++++++++++++++++++++++++++++++++ bin/git/git-svn-abandon-msg-filter | 52 +++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100755 bin/git/git-svn-abandon-cleanup create mode 100755 bin/git/git-svn-abandon-fix-refs create mode 100755 bin/git/git-svn-abandon-msg-filter (limited to 'bin/git') diff --git a/bin/git/git-svn-abandon-cleanup b/bin/git/git-svn-abandon-cleanup new file mode 100755 index 0000000..2e2a547 --- /dev/null +++ b/bin/git/git-svn-abandon-cleanup @@ -0,0 +1,16 @@ +#!/bin/sh + +# strip svk and git-svn noise, retaining tags +git filter-branch --tag-name-filter cat --msg-filter "git svn-abandon-msg-filter" -- --all + +# remove the backup refs +git for-each-ref --format='%(refname)' refs/original/ refs/remotes/svn/ | while read ref; do + git update-ref -d "$ref" +done + +# ditch all pre-conversion objects forcefully +git reflog expire --all --expire=now +git gc --aggressive + +git prune +git fsck --full diff --git a/bin/git/git-svn-abandon-fix-refs b/bin/git/git-svn-abandon-fix-refs new file mode 100755 index 0000000..c47405d --- /dev/null +++ b/bin/git/git-svn-abandon-fix-refs @@ -0,0 +1,63 @@ +#!/bin/sh + +# clean up working dir + +git update-ref -d master + +# create annotated tags out of svn tags +git for-each-ref --format='%(refname)' refs/remotes/svn/tags/* | while read tag_ref; do + tag=${tag_ref#refs/remotes/svn/tags/} + tree=$( git rev-parse "$tag_ref": ) + + # find the oldest ancestor for which the tree is the same + parent_ref="$tag_ref"; + while [ $( git rev-parse --quiet --verify "$parent_ref"^: ) = "$tree" ]; do + parent_ref="$parent_ref"^ + done + parent=$( git rev-parse "$parent_ref" ); + + # if this ancestor is in trunk then we can just tag it + # otherwise the tag has diverged from trunk and it's actually more like a + # branch than a tag + merge=$( git merge-base "refs/remotes/svn/trunk" $parent ); + if [ "$merge" = "$parent" ]; then + target_ref=$parent + else + echo "tag has diverged: $tag" + target_ref="$tag_ref" + fi + + # create an annotated tag based on the last commit in the tag, and delete the "branchy" ref for the tag + git show -s --pretty='format:%s%n%n%b' "$tag_ref" | \ + perl -ne 'next if /^git-svn-id:/; $s++, next if /^\s*r\d+\@.*:.*\|/; s/^ // if $s; print' | \ + env GIT_COMMITTER_NAME="$( git show -s --pretty='format:%an' "$tag_ref" )" \ + GIT_COMMITTER_EMAIL="$( git show -s --pretty='format:%ae' "$tag_ref" )" \ + GIT_COMMITTER_DATE="$( git show -s --pretty='format:%ad' "$tag_ref" )" \ + git tag -a -F - "$tag" "$target_ref" + + git update-ref -d "$tag_ref" +done + +# create local branches out of svn branches +git for-each-ref --format='%(refname)' refs/remotes/svn/ | while read branch_ref; do + branch=${branch_ref#refs/remotes/svn/} + git branch "$branch" "$branch_ref" + git update-ref -d "$branch_ref" +done + +# rename 'trunk' to 'master' +git checkout trunk +git branch -M trunk master + +# remove merged branches +git for-each-ref --format='%(refname)' refs/heads | while read branch; do + git rev-parse --quiet --verify "$branch" || continue # make sure it still exists + git symbolic-ref HEAD "$branch" + git branch -d $( git branch --merged | grep -v '^\*' ) +done + +git checkout master + +# list possible merge commits to help create a grafts file +git log --pretty=one --all -E --grep='[mM]erge|\(orig r' + diff --git a/bin/git/git-svn-abandon-msg-filter b/bin/git/git-svn-abandon-msg-filter new file mode 100755 index 0000000..540b4c8 --- /dev/null +++ b/bin/git/git-svn-abandon-msg-filter @@ -0,0 +1,52 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my $svn_id; +my $msg = ''; + +while (<>) { + if ( /^git-svn-id: (.*)/ ) { + $svn_id = $1; + } else { + $msg .= $_; + } +} + +# if this is a merge commit, rewrite the message to have a better "subject" +if ( $msg =~ /^\s*r\d+\@.*\(orig r\d+\):/ ) { + # print the original message + $msg =~ s/^ //mg; + + my ( $to, @from ) = ( split /\s+/, `git show -s --pretty='format:%P' $ENV{GIT_COMMIT}` ); + + print "Merge ", + join(", ", map { format_branch($_) } @from), + " into ", + format_branch($to), + "\n\n", + $msg; +} else { + if ( $msg =~ s/^\s*r\d+\@.*:.*$//m ) { + $msg =~ s/^ //mg; + } + + print $msg; +} + +sub format_branch { + my $commit = shift; + + my $body = `git show -s --pretty='format:%b' $commit`; + + if ( $body =~ m{git-svn-id: .*/branches/(.*?)\@} ) { + return "'$1'"; + } elsif ( $body =~ m{git-svn-id: .*/trunk\@} ) { + return "'trunk'"; + } elsif ( $body =~ /\@r(\d+)/ ) { + return $1; + } else { + die "unknown rev for $commit"; + } +} -- cgit v1.2.3-54-g00ecf