git-svn: automatically importing/creating svn revi

2019-07-06 12:15发布

问题:

I am using git-svn to work with a svn repository. The git master branch is mirroring the svn trunk branch (the only svn branch in use), i.e. there is a one to one relation between elements on the master branch and the trunk branch.

I want to have git tags that corresponds to svn revisions, so that I can do things like for instance git diff r123 workbranch to see what I have done compared to svn revision 123.

The revisions are not tagged when I do git svn rebase, so I have created the following script that I run post svn rebase:

#!/usr/bin/perl 

use strict;
use warnings;

open(PIPE, "git log master |");
# Format for the pipe output:
# ...
# commit 6b24b8fdc6a25d35b01140dc1ac054697133423d
# ...
#      git-svn-id: https://server.example.com/svn/project/trunk@594 164096ca-3471-41d1-a9ce-9541462a8c31
# ...
my $commit = "";
my $i = 0;
foreach my $line (<PIPE>) {
    if ($line =~ /^commit ([\da-f]+)/) {
        $commit = $1;
        next;
    }
    next unless $line =~ /^\s+git-svn-id: .*\/trunk\@(\d+) /;
    my $git_svn_id = $1;
    run("git", "tag", "-f", "r$git_svn_id", $commit);
    last if $i++ == 20;
}
close(PIPE);

sub run {
    print join(' ', @_), "\n";
    return system(@_);
}

This script gets the job done, but I have to run it manually every time, and I have (arbitrarily) capped it at checking the last 21 revisions so there is a theoretical risk of missing some (but I will see that from the printing).

The question: Is there any way I can automate this so that I just run git svn rebase and all imported revisions will be tagged in git? Any hooks I can use?

PS Yes, I am aware of svn find-rev, but I want in absolutely no way having to write commands as complicated as git diff $(git svn find-rev r123) $(git svn find-rev r124) instead of just git diff r123 r124.

回答1:

Here's a crazy idea: Trap bash commands and automatically replace any r1234 strings with SHA hashes:

shopt -s extdebug

enhance_rev_parse () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    case "$BASH_COMMAND" in
    *r[0-9]*)
        eval $(echo "$BASH_COMMAND" | sed -e 's/r[0-9][0-9]*/$(git svn find-rev &)/g')
        return 1
        ;;
    esac
}

trap 'enhance_rev_parse' DEBUG


回答2:

Short Answer and Caveats

There is not a way to hook the git svn rebase command that I'm aware of (or git svn dcommit).

What you can do is use the post-rebase hook. However, this is only invoked when the history is actually updated by the rebase -- if you run git svn rebase and there's no new SVN commits that affect the current Git branch, no changes will take effect.

Ensure You Used --stdlayout

With regard to creating Git tags for SVN tags in a single command, if you did not originally clone the repository with...

git svn clone --stdlayout

I would recommend that you re-clone the repository. This will make your life much easier.

Telling Git About New SVN Tags

To tell Git about new SVN tags and branches, use the command git svn fetch --all. The command git svn rebase --fetch-all also performs this action.

Automatically git tag all SVN tags

In order to convert thse newly-fetched SVN tags into Git tags, one way is to just walk the the references.

#!/bin/sh
git svn fetch --all &&
git for-each-ref refs/remotes/origin/tags |
while read ref
do
  tagName=$(echo $ref | cut --delimiter / --fields=5)
  git tag -f "$tagName" "refs/remotes/origin/tags/$ref"
done

Put this file as .git/hooks/post-rebase.