我目前正在镜像Github上的现有SVN存储库。对于初始克隆,我做了这个:
git svn --authors-prog=fixsvnauthors clone http://closure-compiler.googlecode.com/svn/
要每小时更新一次回购,我会这样做:
git svn --authors-prog=fixsvnauthors rebase
fixsvnauthors
将SVN用户名(电子邮件地址)映射到Git用户名。我的问题是,这个SVN存储库似乎对提交消息有一个奇怪的策略。他们中的大多数都以空行开头。 Github完全不喜欢这样。所有提交消息摘要都是空的,这很烦人。
因此,当克隆过程中有一种很好的方法来修复作者时,也有一种修复提交消息的方法吗?我只想 修剪 提交消息,以便Github正确读取它们。在git-svn的文档中找不到这样的东西,但也许我错过了什么。那我怎么能这样做呢?
答案 0 :(得分:1)
我创建了一个Git补丁来实现--messages-prog
中的git-svn
参数,该参数可用于指定一个程序来过滤提交消息,同时从SVN中提取更改。对我来说很棒。我将补丁发送到git邮件列表但从未得到任何反应。好吧,也许修补程序对某人有用,所以我在这里发布:
From: Klaus Reimer <k@ailis.de>
Date: Sat, 26 May 2012 17:56:42 +0200
Subject: [PATCH] Implement --messages-prog parameter in git-svn
Some SVN repositories have strange policies for commit messages requiring an
empty line at the top of the commit message. When you clone these
repositories with Git to mirror them on GitHub then no commit message
summaries are displayed at all at GitHub because they use the first line for
it (Which is empty). You always have to open the commit message details
instead which is pretty annoying. With the --messages-prog parameter you
can specify a program which can modify the SVN commit message before
committing it into the Git repo. This works like the --authors-prog
parameter with the only difference that the commit message is piped into the
specified program instead of being passed to it as a command-line argument.
The same could be achieved by a "trim" feature but specifying a program
which can modify any aspect of a commit message is much more flexible.
Signed-off-by: Klaus Reimer <k@ailis.de>
---
Documentation/git-svn.txt | 5 +++++
git-svn.perl | 26 +++++++++++++++++++++++++-
t/t9147-git-svn-messages-prog.sh | 40 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 70 insertions(+), 1 deletion(-)
create mode 100755 t/t9147-git-svn-messages-prog.sh
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index cfe8d2b..7289246 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -546,6 +546,11 @@ config key: svn.authorsfile
expected to return a single line of the form "Name <email>",
which will be treated as if included in the authors file.
+--messages-prog=<filename>::
+ If this option is specified, each SVN commit message is piped
+ through the given program. The output of this program is then
+ used as the new commit message instead.
+
-q::
--quiet::
Make 'git svn' less verbose. Specify a second time to make it
diff --git a/git-svn.perl b/git-svn.perl
index c84842f..514c888 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -6,7 +6,7 @@ use warnings;
use strict;
use vars qw/ $AUTHOR $VERSION
$sha1 $sha1_short $_revision $_repository
- $_q $_authors $_authors_prog %users/;
+ $_q $_authors $_authors_prog $_messages_prog %users/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '@@GIT_VERSION@@';
@@ -120,6 +120,7 @@ my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
'authors-file|A=s' => \$_authors,
'authors-prog=s' => \$_authors_prog,
+ 'messages-prog=s' => \$_messages_prog,
'repack:i' => \$Git::SVN::_repack,
'noMetadata' => \$Git::SVN::_no_metadata,
'useSvmProps' => \$Git::SVN::_use_svm_props,
@@ -359,6 +360,9 @@ load_authors() if $_authors;
if (defined $_authors_prog) {
$_authors_prog = "'" . File::Spec->rel2abs($_authors_prog) . "'";
}
+if (defined $_messages_prog) {
+ $_messages_prog = "'" . File::Spec->rel2abs($_messages_prog) . "'";
+}
unless ($cmd =~ /^(?:clone|init|multi-init|commit-diff)$/) {
Git::SVN::Migration::migration_check();
@@ -2051,6 +2055,7 @@ use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent
use Carp qw/croak/;
use File::Path qw/mkpath/;
use File::Copy qw/copy/;
+use IPC::Open2;
use IPC::Open3;
use Time::Local;
use Memoize; # core since 5.8.0, Jul 2002
@@ -3409,6 +3414,22 @@ sub other_gs {
$gs
}
+sub call_messages_prog {
+ my ($orig_message) = @_;
+ my ($pid, $in, $out);
+
+ $pid = open2($in, $out, $::_messages_prog)
+ or die "$::_messages_prog failed with exit code $?\n";
+ print $out $orig_message;
+ close($out);
+ my ($message) = "";
+ while (<$in>) {
+ $message .= $_;
+ }
+ close($in);
+ return $message;
+}
+
sub call_authors_prog {
my ($orig_author) = @_;
$orig_author = command_oneline('rev-parse', '--sq-quote', $orig_author);
@@ -3809,6 +3830,9 @@ sub make_log_entry {
$log_entry{date} = parse_svn_date($log_entry{date});
$log_entry{log} .= "\n";
+ if (defined $::_messages_prog) {
+ $log_entry{log} = call_messages_prog($log_entry{log});
+ }
my $author = $log_entry{author} = check_author($log_entry{author});
my ($name, $email) = defined $::users{$author} ? @{$::users{$author}}
: ($author, undef);
diff --git a/t/t9147-git-svn-messages-prog.sh b/t/t9147-git-svn-messages-prog.sh
new file mode 100755
index 0000000..ebb42b0
--- /dev/null
+++ b/t/t9147-git-svn-messages-prog.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='git svn messages prog tests'
+
+. ./lib-git-svn.sh
+
+cat > svn-messages-prog <<'EOF'
+#!/bin/sh
+sed s/foo/bar/g
+EOF
+chmod +x svn-messages-prog
+
+test_expect_success 'setup svnrepo' '
+ svn mkdir -m "Unchanged message" "$svnrepo"/a
+ svn mkdir -m "Changed message: foo" "$svnrepo"/b
+ '
+
+test_expect_success 'import messages with prog' '
+ git svn clone --messages-prog=./svn-messages-prog \
+ "$svnrepo" x
+ '
+
+test_expect_success 'imported 2 revisions successfully' '
+ (
+ cd x
+ test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2
+ )
+ '
+
+test_expect_success 'messages-prog ran correctly' '
+ (
+ cd x
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
+ grep "^ Unchanged message" &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~0 | \
+ grep "^ Changed message: bar"
+ )
+ '
+
+test_done
-- 1.7.10.2.605.gbefc5ed.dirty
答案 1 :(得分:0)
我没有找到允许您在首次导入后保留git-svn
链接的解决方案。
对于一次性导入,我认为最好将这种修复作为一个单独的步骤,在 git-svn
导入后完成。
从理论上讲,git grafts可用于将原始git仓库中的后续git-svn
导入附加到您的固定git仓库。
但是git svn dcommit
(导出回svn repo)不太可能有效。
为了确保处理并修复所有分支的所有提交,您可以使用
git filter-branch -f --msg-filter 'yourScript.sh' --tag-name-filter cat -- --all
如“Rewriting git commit message history across multiple branches”
中所述
filter-branch
非常强大,有很多选择 在这种情况下,我只想重写一个提交消息,所以我使用了--msg-filter
选项:它将每条消息传递给一个shell命令,并将其替换为该命令的输出。
与基于单个编辑的提交重新绑定不同,此方法允许您以编程方式编辑所有提交消息。如果您有任何标记,则应添加
--tag-name-filter cat
这会更新标记以指向修改后的提交。如果标签已签名,则会更复杂。
答案 2 :(得分:0)
导入完成后,您也可以替换空消息。
git filter-branch --msg-filter '<path>\SetDefaultMessage.pl'
其中SetDefaultMessage.pl是
#!/usr/bin/perl
my $data = "";
while(<STDIN>) {
$data .= $_;
}
if($data =~ /^\s*$/) { $data="-\n"; }
print "$data";