@@ -374,16 +374,9 @@ sub cmd_dcommit {
374374 die " Unable to determine upstream SVN information from " ,
375375 " $head history\n " ;
376376 }
377- my $c = $refs [-1];
378377 my $last_rev ;
379- foreach my $d (@refs ) {
380- if (!verify_ref(" $d ~1" )) {
381- fatal " Commit $d \n " ,
382- " has no parent commit, and therefore " ,
383- " nothing to diff against.\n " ,
384- " You should be working from a repository " ,
385- " originally created by git-svn\n " ;
386- }
378+ my ($linear_refs , $parents ) = linearize_history($gs , \@refs );
379+ foreach my $d (@$linear_refs ) {
387380 unless (defined $last_rev ) {
388381 (undef , $last_rev , undef ) = cmt_metadata(" $d ~1" );
389382 unless (defined $last_rev ) {
@@ -405,6 +398,9 @@ sub cmd_dcommit {
405398 svn_path => ' ' );
406399 if (!SVN::Git::Editor-> new(\%ed_opts )-> apply_diff) {
407400 print " No changes\n $d ~1 == $d \n " ;
401+ } elsif ($parents -> {$d } && @{$parents -> {$d }}) {
402+ $gs -> {inject_parents_dcommit }-> {$last_rev } =
403+ $parents -> {$d };
408404 }
409405 }
410406 }
@@ -831,6 +827,59 @@ sub working_head_info {
831827 (undef , undef , undef , undef );
832828}
833829
830+ sub read_commit_parents {
831+ my ($parents , $c ) = @_ ;
832+ my ($fh , $ctx ) = command_output_pipe(qw/ cat-file commit/ , $c );
833+ while (<$fh >) {
834+ chomp ;
835+ last if ' ' ;
836+ / ^parent ($sha1 )/ or next ;
837+ push @{$parents -> {$c }}, $1 ;
838+ }
839+ close $fh ; # break the pipe
840+ }
841+
842+ sub linearize_history {
843+ my ($gs , $refs ) = @_ ;
844+ my %parents ;
845+ foreach my $c (@$refs ) {
846+ read_commit_parents(\%parents , $c );
847+ }
848+
849+ my @linear_refs ;
850+ my %skip = ();
851+ my $last_svn_commit = $gs -> last_commit;
852+ foreach my $c (reverse @$refs ) {
853+ next if $c eq $last_svn_commit ;
854+ last if $skip {$c };
855+
856+ unshift @linear_refs , $c ;
857+ $skip {$c } = 1;
858+
859+ # we only want the first parent to diff against for linear
860+ # history, we save the rest to inject when we finalize the
861+ # svn commit
862+ my $fp_a = verify_ref(" $c ~1" );
863+ my $fp_b = shift @{$parents {$c }} if $parents {$c };
864+ if (!$fp_a || !$fp_b ) {
865+ die " Commit $c \n " ,
866+ " has no parent commit, and therefore " ,
867+ " nothing to diff against.\n " ,
868+ " You should be working from a repository " ,
869+ " originally created by git-svn\n " ;
870+ }
871+ if ($fp_a ne $fp_b ) {
872+ die " $c ~1 = $fp_a , however parsing commit $c " ,
873+ " revealed that:\n $c ~1 = $fp_b \n BUG!\n " ;
874+ }
875+
876+ foreach my $p (@{$parents {$c }}) {
877+ $skip {$p } = 1;
878+ }
879+ }
880+ (\@linear_refs , \%parents );
881+ }
882+
834883package Git::SVN ;
835884use strict;
836885use warnings;
@@ -1551,6 +1600,11 @@ sub get_commit_parents {
15511600 if (my $cur = ::verify_ref($self -> refname.' ^0' )) {
15521601 push @tmp , $cur ;
15531602 }
1603+ if (my $ipd = $self -> {inject_parents_dcommit }) {
1604+ if (my $commit = delete $ipd -> {$log_entry -> {revision }}) {
1605+ push @tmp , @$commit ;
1606+ }
1607+ }
15541608 push @tmp , $_ foreach (@{$log_entry -> {parents }}, @tmp );
15551609 while (my $p = shift @tmp ) {
15561610 next if $seen {$p };
0 commit comments