24

I'm trying to use git on top of an older subversion repository. We have multiple users working on the new git remote (origin/master) which is a git svn clone of the older repo. The problem is when we do a git svn dcommit to push changes from the new git repo to the old subversion repo, the commiter's username is lost and instead is replaced by the git svn clone'd user's information. Is there a way to preserve the commiter's info into the subversion upon a dcommit?

Tobu
  • 24,771
  • 4
  • 91
  • 98
tonycoco
  • 531
  • 7
  • 9
  • So you have cloned the SVN only once and than done a git clone of the svn cloned repo? – khmarbaise Mar 16 '11 at 16:46
  • I logged a bug report on this on the debian package at: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=966476 It also includes an updated of Adam Sutton;s patch which applies to a more recent version of git-svn – Andrew Jul 29 '20 at 01:47

6 Answers6

5

You can use git-svn with --add-author-from and --use-log-author. The former represents the git author in a From: line in the commit message, the latter does the reverse transformation.

That said, repository formats matter, and the subversion repository format is poorer than the git one. It doesn't support merging well, or committers vs authors or commit times distinct from push times. git-svn is OK to get the git ui locally, but it can't do much about the data model. Hopefully you'll be able to migrate to a git repository, possibly with an svn frontend (right now there is git-svnserver and github's closed source option).

Tobu
  • 24,771
  • 4
  • 91
  • 98
  • 1
    It only keeps the committer information as a comment in the commit message. It does not pushes the changes as the proper committer. – Vicente Quintans Jun 19 '14 at 16:20
  • 1
    Yes. The proper committer could only be determined through an external mapping, because username conventions aren't the same (email-style for git, tied to authentication for svn). – Tobu Jun 20 '14 at 17:22
1

I know this is a very old topic, but if anyone is interested I added this hack to my local copy of 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;

This is against 1.9.1-1 (deb package version on Ubuntu 14.04). It's not configurable, in the sense that if you've got a users.txt file it will use it, and it will always try and set the date. Also if you have multiple SVN accounts for a given git user it will just pick one.

And I'm only just starting to use it in anger, but I think it might do the job, fingers crossed!

Regards Adam

1

I modified a bit the patch proposed by Adam Sutton so that git svn dcommit accepts --commit-author option:

--- ./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 $!;
Community
  • 1
  • 1
Max
  • 34
  • 3
0

This is another slightly modified version from Adam Sutton's Answer It creates a reverse mapping from the authors file and does some extra checking for duplicate and/or missing authors. It also tells you in the input which Git user was mapped to which SVN user for each commit, even when running git svn dcommit --dry-run.

[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;
David Miler
  • 100
  • 2
  • 14
0

Require everyone to use a "signed-off-by" or some other way of including their username in the message of every commit. It's a pretty ugly solution, but AFAIK the only thing you can do without hacking the git-svn source.

Tyler
  • 21,762
  • 11
  • 61
  • 90
-2

Github to the rescue as usual! Their quick overview of git svn goes into user mapping: http://help.github.com/svn-importing/

Basically, you create a file that contains the mappings you want.

EDIT: the GitHub link above is dead (if I can find similar info, I’ll post the new URL), but the --authors-file (-A) option in git svn appears to do bidirectional mapping; see the official docs at https://git-scm.com/docs/git-svn.

Marnen Laibow-Koser
  • 5,959
  • 1
  • 28
  • 33
  • 3
    I'm not sure that's going to work. The author mapping is for importing SVN into Git, not for dcommitting your Git commits back into SVN. – awendt May 04 '11 at 12:56
  • It works both ways, I believe. Certainly I've used git-svn to work with SVN repositories, not just as an import tool. – Marnen Laibow-Koser May 17 '11 at 14:12
  • This doesn't explain how to do anything, the link no longer contains the user mapping information, and even if it did, I don't think it works when you're pushing to svn – Michael Mrozek May 23 '13 at 19:28
  • @MichaelMrozek My recollection is that it does work when you're pushing to SVN. Why tell me it doesn't without even trying? – Marnen Laibow-Koser May 29 '13 at 15:52
  • @MarnenLaibow-Koser Because your answer doesn't actually say *what* to try, and the link doesn't either; it's entirely about importing from SVN, not committing to it. That was my point: somebody should be able to read the answer and know exactly what to do, they shouldn't need to go to other websites to figure it out – Michael Mrozek May 29 '13 at 17:36
  • @MichaelMrozek The link provided the necessary information when I posted it; I can't be held responsible for third-party sites changing. "they shouldn't need to go to other websites to figure it out" — In many cases, I disagree with that, because some issues are more complex than Stack Overflow is suited for. Anyway, here's further info: the git-svn authors file (`git-svn -A` or the `svn.authorsfile` config property) seems to do bidirectional mappings, or so say documents like http://wiki.apache.org/general/GitAtApache . I no longer use SVN, but if you do, try this trick out and let me know! – Marnen Laibow-Koser Jun 01 '13 at 05:15
  • @MichaelMrozek I should mention that I remember using `git-svn` with bidirectional user mappings, I just don't remember precisely how I set it up. So it is possible. – Marnen Laibow-Koser Jun 01 '13 at 05:18
  • @MarnenLaibow-Koser All links are dead. Adding your comment to the answer. – Burak May 10 '23 at 07:13
  • @Burak Oh yuck. I wonder if I can find better URLs for that content. • I appreciate what you were trying to do by adding my comment into the main answer, but I think that change might have taken it out of context and changed the sense of the answer more than we’re supposed to. – Marnen Laibow-Koser May 11 '23 at 23:11
  • @MarnenLaibow-Koser Either that, or this post will be deleted because of it being a link-only answer. It's better than nothing and provides a clue about what to do. I agree that this is not a complete answer. Feel free to improve by providing some example usage and reference to documentation. – Burak May 12 '23 at 14:27
  • OK, I rewrote and added a link to the official docs, which shouldn’t go away. – Marnen Laibow-Koser May 13 '23 at 16:27