git svn dcommit如何使用svn用户名?

24

我想在旧的Subversion存储库上使用Git。我们有多个用户在新的Git远程(origin/master)上工作,该远程是旧存储库的Git SVN克隆版本。问题是,当我们使用git svn dcommit将更改从新的Git存储库推送到旧的Subversion存储库时,提交者的用户名丢失,并被替换为Git SVN克隆用户的信息。是否有一种方法可以在dcommit期间将提交者的信息保留到Subversion中?


你只克隆了 SVN 一次,然后对已经克隆的 SVN 仓库进行了 git 克隆? - khmarbaise
我在Debian软件包上记录了一个错误报告,网址为:https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=966476。它还包括了Adam Sutton的更新补丁,适用于更近期的git-svn版本。 - Andrew
6个回答

5
你可以使用git-svn的--add-author-from--use-log-author选项。前者在提交消息的From:行中表示git作者,后者执行反向转换。
话虽如此,仓库格式很重要,而Subversion仓库格式比Git差。它不支持合并、区分提交者和作者或提交时间与推送时间不同。git-svn对于本地获取git用户界面还算可以,但它无法处理数据模型。希望您能够迁移到一个Git仓库,可能带有一个svn前端(现在有git-svnserver和github的闭源选项)。

1
它只将提交者信息作为注释保存在提交消息中,而不将更改作为正确的提交者推送。 - Vicente Quintans
1
是的。正确的提交者只能通过外部映射确定,因为用户名约定不同(git使用电子邮件样式,svn绑定到身份验证)。 - Tobu

1

我对Adam Sutton提出的补丁进行了一些修改,以便git svn dcommit接受--commit-author选项:

--- ./git-svn.orig  2014-10-09 23:11:40.032767542 +0300
+++ ./git-svn   2014-10-09 23:27:58.252753020 +0300
@@ -116,7 +116,7 @@
    $_before, $_after,
    $_merge, $_strategy, $_preserve_merges, $_dry_run, $_parents, $_local,
    $_prefix, $_no_checkout, $_url, $_verbose,
-   $_commit_url, $_tag, $_merge_info, $_interactive);
+   $_commit_url, $_commit_author, $_tag, $_merge_info, $_interactive);

 # This is a refactoring artifact so Git::SVN can get at this git-svn switch.
 sub opt_prefix { return $_prefix || '' }
@@ -194,6 +194,7 @@
              'dry-run|n' => \$_dry_run,
              'fetch-all|all' => \$_fetch_all,
              'commit-url=s' => \$_commit_url,
+             'commit-author=s' => \$_commit_author,
              'revision|r=i' => \$_revision,
              'no-rebase' => \$_no_rebase,
              'mergeinfo=s' => \$_merge_info,
@@ -982,6 +983,7 @@
                                             $rewritten_parent);
            }

+           my $ra = Git::SVN::Ra->new($url);
            my %ed_opts = ( r => $last_rev,
                            log => get_commit_entry($d)->{log},
                            ra => $ra,
@@ -993,6 +995,10 @@
                            editor_cb => sub {
                                   print "Committed r$_[0]\n";
                                   $cmt_rev = $_[0];
+                                  if (defined($_commit_author)) {
+                                    print "Changed author to $_commit_author\n";
+                                    $ra->change_rev_prop($cmt_rev, 'svn:author', $_commit_author);
+                                  }
                            },
                    mergeinfo => $_merge_info,
                            svn_path => '');
@@ -1790,6 +1796,7 @@
        }
        print $log_fh $msgbuf or croak $!;
        command_close_pipe($msg_fh, $ctx);
+       $log_entry{author} = $author || undef;
    }
    close $log_fh or croak $!;

1

我知道这是一个非常老的话题,但如果有人感兴趣,我已经将此hack添加到我的本地git-svn副本中:

23a24
> use POSIX qw/strftime/;
984a986
>           my $ra = Git::SVN::Ra->new($url);
987c989
<                           ra => Git::SVN::Ra->new($url),
---
>                           ra => $ra,
995a998,1014
>                                  my $cmt_author = get_commit_entry($d)->{author};
>                                  my $cmt_date   = get_commit_entry($d)->{date};
>                                  if ( defined $cmt_author ) {
>                                    foreach my $key ( keys %users ) {
>                                      my $i = index($cmt_author, $users{$key}[1]);
>                                      if ( $i != -1 ) {
>                                        print "Changed author to $key\n";
>                                        $ra->change_rev_prop($cmt_rev, 'svn:author', $key);
>                                        last;
>                                      }
>                                    }
>                                  }
>                                  if ( defined $cmt_date ) {
>                                    $cmt_date = strftime("%Y-%m-%dT%H:%M:%S.000000Z", gmtime($cmt_date));
>                                    print "Changed date to $cmt_date\n";
>                                    $ra->change_rev_prop($cmt_rev, 'svn:date', $cmt_date);
>                                  }
1758c1777
<   my %log_entry = ( log => '', tree => get_tree_from_treeish($treeish) );
---
>   my %log_entry = ( log => '', tree => get_tree_from_treeish($treeish), author => undef, date => undef );
1768a1788
>       my $date;
1774c1794,1797
<               $author = $1 if (/^author (.*>)/);
---
>           if (/^author (.*>) (\d+) ([\-\+]?\d+)$/o) {
>                 $author = $1;
>               $date   = Git::SVN::Log::parse_git_date($2, $3);
>         }
1792a1816,1817
>       $log_entry{author} = $author || undef;
>       $log_entry{date}   = $date   || undef;

这是针对1.9.1-1(Ubuntu 14.04上的deb软件包版本)的。它不可配置,如果你有一个users.txt文件,它将使用它,并且总是尝试设置日期。而且,如果给定的git用户有多个SVN帐户,它只会选择一个。我刚开始使用它,并希望它能够胜任工作。祝好!谢谢。

0

要求每个人在每次提交时使用“signed-off-by”或其他方式将其用户名包含在提交信息中。这是一种相当不雅的解决方案,但据我所知,这是在不修改git-svn源代码的情况下所能做的唯一事情。


如果我正确理解了需求,那么这并不是真的。请查看我的答案以获取实际解决方案。 - Marnen Laibow-Koser

0

这是Adam Sutton答案的另一个稍作修改的版本。 它从作者文件创建了一个反向映射,并对重复和/或缺失的作者进行了一些额外的检查。 即使在运行git svn dcommit --dry-run时,它也会告诉您哪个Git用户被映射到哪个SVN用户的每个提交输入。

[root@qa-travel-centos git-svn-bridge]# diff scripts/git-svn.orig scripts/git-svn.hacked
23a24
> use POSIX;
963a965,975
>
>       #Revert the keys/values from authors into a reverse map.
>       #If a duplicate is found(i.e. 2 git users matching 1 svn user) abort the operation.
>       my %rev_author_map;
>       while (my ($key, @value) = each %users) {
>         my $rev_key="$value[0][0] <$value[0][1]>";
>         if(exists $rev_author_map{$rev_key}) {
>             fatal "Found a duplicate GIT author($rev_key) in the authorsfile. Aborting dcommit!"
>         }
>         $rev_author_map{$rev_key}=$key
>       }
972a985,997
>               my $commit_entry = get_commit_entry($d);
>                 my $cmt_author = $commit_entry->{author};
>                 my $cmt_date = $commit_entry->{date};
>                 print "GIT AUTHOR: $cmt_author; \n";
>                 if(defined $cmt_author) {
>                   my $svn_author = $rev_author_map{$cmt_author};
>                 #Here we check if the git commit author matches an author in the authorsfile
>                   if ((not (defined $svn_author)) || $svn_author eq "") {
>                   fatal "The git author: $cmt_author was not found in the authors file. Make sure you have commited as a user listed in the authors file. Note:matching is case sensitive.";
>                   }
>                 print "SVN AUTHOR: $svn_author\n";
>                 }
>
984c1009
<
---
>                       my $ra = Git::SVN::Ra->new($url);
987c1012
<                                       ra => Git::SVN::Ra->new($url),
---
>                                       ra => $ra,
995a1021,1032
>                                              #Here we coerce SVN into accepting the correct user according to the reverse mapping.
>                                               if(defined $cmt_author) {
>                                                 my $svn_author = $rev_author_map{$cmt_author};
>                                                 print "SVN AUTHOR: $svn_author\n";
>                                                 $ra->change_rev_prop($cmt_rev, 'svn:author', $svn_author)
>                                               }
>                                              #Here we coerce SVN into accepting the commit date from Git.
>                                               if ( defined $cmt_date ) {
>                                                 $cmt_date = strftime("%Y-%m-%dT%H:%M:%S.000000Z", gmtime($cmt_date));
>                                                 print "SVN DATE SET TO: $cmt_date\n";
>                                                 $ra->change_rev_prop($cmt_rev, 'svn:date', $cmt_date);
>                                               }
1748c1785
<       my %log_entry = ( log => '', tree => get_tree_from_treeish($treeish) );
---
>       my %log_entry = ( log => '', tree => get_tree_from_treeish($treeish), author =>undef, date => undef );
1758a1796
>               my $date;
1764c1802,1805
<                               $author = $1 if (/^author (.*>)/);
---
>                               if(/^author (.*>) (\d+) ([\-\+]?\d+)$/o){
>                                 $author = $1;
>                                 $date = $2;
>                               }
1782a1824,1825
>               $log_entry{author} = $author || undef;
>               $log_entry{date} = $date || undef;

-2

Github一如既往地提供了解救!他们快速介绍git svn中的用户映射:http://help.github.com/svn-importing/

基本上,您可以创建一个包含所需映射的文件。

编辑:上述的GitHub链接已失效(如果我能找到类似的信息,我会发布新的URL),但git svn中的--authors-file-A)选项似乎可以实现双向映射;请参阅官方文档 https://git-scm.com/docs/git-svn


3
我不确定那会起作用。该作者映射是用于将SVN导入Git,而不是将你的Git提交记录推回SVN。 - awendt
我相信它可以双向工作。确实,我已经使用git-svn来处理SVN仓库,而不仅仅是作为一个导入工具。 - Marnen Laibow-Koser
这并没有解释如何做任何事情,链接不再包含用户映射信息,即使它包含了,我认为在推送到svn时也不起作用。 - Michael Mrozek
@MichaelMrozek 我记得当你推送到 SVN 时它是可以工作的。为什么不试一下就告诉我它不行呢? - Marnen Laibow-Koser
@MarnenLaibow-Koser 因为你的回答实际上并没有说要尝试什么,链接也没有;它完全是关于从SVN导入,而不是提交到它。这就是我的观点:有人应该能够阅读答案并确切地知道该怎么做,他们不应该需要去其他网站找出答案。 - Michael Mrozek
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接