Skip to content

Commit c74d9ac

Browse files
Eric Wonggitster
authored andcommitted
git-svn: fix dcommit clobbering when committing a series of diffs
Our revision number sent to SVN is set to the last revision we committed if we've made any previous commits in a dcommit invocation. Although our SVN Editor code uses the delta of two (old) trees to generate information to send upstream, it'll still send complete resultant files upstream; even if the tree they're based against is out-of-date. The combination of sending a file that does not include the latest changes, but set with a revision number of a commit we just made will cause SVN to accept the resultant file even if it was generated against an old tree. More trouble was caused when fixing this because we were rebasing uncessarily at times. We used git-diff-tree to check the imported SVN revision against our HEAD, not the last tree we committed to SVN. The unnecessary rebasing caused merge commits upstream to SVN to fail. Signed-off-by: Eric Wong <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ee78740 commit c74d9ac

File tree

2 files changed

+100
-4
lines changed

2 files changed

+100
-4
lines changed

git-svn.perl

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@ sub cmd_dcommit {
390390
"If these changes depend on each other, re-running ",
391391
"without --no-rebase will be required."
392392
}
393-
foreach my $d (@$linear_refs) {
393+
while (1) {
394+
my $d = shift @$linear_refs or last;
394395
unless (defined $last_rev) {
395396
(undef, $last_rev, undef) = cmt_metadata("$d~1");
396397
unless (defined $last_rev) {
@@ -423,14 +424,14 @@ sub cmd_dcommit {
423424

424425
# we always want to rebase against the current HEAD,
425426
# not any head that was passed to us
426-
my @diff = command('diff-tree', 'HEAD',
427+
my @diff = command('diff-tree', $d,
427428
$gs->refname, '--');
428429
my @finish;
429430
if (@diff) {
430431
@finish = rebase_cmd();
431-
print STDERR "W: HEAD and ", $gs->refname,
432+
print STDERR "W: $d and ", $gs->refname,
432433
" differ, using @finish:\n",
433-
"@diff";
434+
join("\n", @diff), "\n";
434435
} else {
435436
print "No changes between current HEAD and ",
436437
$gs->refname,
@@ -439,6 +440,45 @@ sub cmd_dcommit {
439440
@finish = qw/reset --mixed/;
440441
}
441442
command_noisy(@finish, $gs->refname);
443+
if (@diff) {
444+
@refs = ();
445+
my ($url_, $rev_, $uuid_, $gs_) =
446+
working_head_info($head, \@refs);
447+
my ($linear_refs_, $parents_) =
448+
linearize_history($gs_, \@refs);
449+
if (scalar(@$linear_refs) !=
450+
scalar(@$linear_refs_)) {
451+
fatal "# of revisions changed ",
452+
"\nbefore:\n",
453+
join("\n", @$linear_refs),
454+
"\n\nafter:\n",
455+
join("\n", @$linear_refs_), "\n",
456+
'If you are attempting to commit ',
457+
"merges, try running:\n\t",
458+
'git rebase --interactive',
459+
'--preserve-merges ',
460+
$gs->refname,
461+
"\nBefore dcommitting";
462+
}
463+
if ($url_ ne $url) {
464+
fatal "URL mismatch after rebase: ",
465+
"$url_ != $url";
466+
}
467+
if ($uuid_ ne $uuid) {
468+
fatal "uuid mismatch after rebase: ",
469+
"$uuid_ != $uuid";
470+
}
471+
# remap parents
472+
my (%p, @l, $i);
473+
for ($i = 0; $i < scalar @$linear_refs; $i++) {
474+
my $new = $linear_refs_->[$i] or next;
475+
$p{$new} =
476+
$parents->{$linear_refs->[$i]};
477+
push @l, $new;
478+
}
479+
$parents = \%p;
480+
$linear_refs = \@l;
481+
}
442482
$last_rev = $cmt_rev;
443483
}
444484
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2007 Eric Wong
4+
test_description='git-svn dcommit clobber series'
5+
. ./lib-git-svn.sh
6+
7+
test_expect_success 'initialize repo' "
8+
mkdir import &&
9+
cd import &&
10+
awk 'BEGIN { for (i = 1; i < 64; i++) { print i } }' > file
11+
svn import -m 'initial' . $svnrepo &&
12+
cd .. &&
13+
git svn init $svnrepo &&
14+
git svn fetch &&
15+
test -e file
16+
"
17+
18+
test_expect_success '(supposedly) non-conflicting change from SVN' "
19+
test x\"\`sed -n -e 58p < file\`\" = x58 &&
20+
test x\"\`sed -n -e 61p < file\`\" = x61 &&
21+
svn co $svnrepo tmp &&
22+
cd tmp &&
23+
perl -i -p -e 's/^58\$/5588/' file &&
24+
perl -i -p -e 's/^61\$/6611/' file &&
25+
test x\"\`sed -n -e 58p < file\`\" = x5588 &&
26+
test x\"\`sed -n -e 61p < file\`\" = x6611 &&
27+
svn commit -m '58 => 5588, 61 => 6611' &&
28+
cd ..
29+
"
30+
31+
test_expect_success 'some unrelated changes to git' "
32+
echo hi > life &&
33+
git update-index --add life &&
34+
git commit -m hi-life &&
35+
echo bye >> life &&
36+
git commit -m bye-life life
37+
"
38+
39+
test_expect_success 'change file but in unrelated area' "
40+
test x\"\`sed -n -e 4p < file\`\" = x4 &&
41+
test x\"\`sed -n -e 7p < file\`\" = x7 &&
42+
perl -i -p -e 's/^4\$/4444/' file &&
43+
perl -i -p -e 's/^7\$/7777/' file &&
44+
test x\"\`sed -n -e 4p < file\`\" = x4444 &&
45+
test x\"\`sed -n -e 7p < file\`\" = x7777 &&
46+
git commit -m '4 => 4444, 7 => 7777' file &&
47+
git svn dcommit &&
48+
svn up tmp &&
49+
cd tmp &&
50+
test x\"\`sed -n -e 4p < file\`\" = x4444 &&
51+
test x\"\`sed -n -e 7p < file\`\" = x7777 &&
52+
test x\"\`sed -n -e 58p < file\`\" = x5588 &&
53+
test x\"\`sed -n -e 61p < file\`\" = x6611
54+
"
55+
56+
test_done

0 commit comments

Comments
 (0)