Subject: Re: git-svn can lose changes silently

From: Seth Falcon <[email-masked]>
Date: Wed, 08 Nov 2006 23:33:53 -0800

Steven Grimm <[email-masked]> writes:

> git-svn is happy to overwrite changes in the svn repository with no
> warnings. Didn't seem to be known behavior when I mentioned it in
> #git, so here's an example, starting completely from scratch to make
> it easier to reproduce. I'm using git-svn 1.4.3 and svn 1.2.3 on OS
> X.

I can reproduce your example and also see the same thing when
accessing an svn repository via https [I've never used the local
file:// mode and was leary of it].

> It is probably not a feature that you can lose changes without knowing
> about it! Even if I'd run git-svn fetch before that commit, it still
> wouldn't help if the svn version of the file changed between the time
> I ran fetch and the time I ran dcommit, totally possible with a busy
> svn repository.
>
> Opinions? Suggestions on fixing it? Do other people agree this is a
> bug?

I think this is a pretty big deal -- at least in terms of user
expectation.  The man page for 'git-svn commit' warns that upstream
changes will be lost.  But in suggesting to use 'git-svn dcommit'
instead, one might expect (hope?) this overwritting upstream changes
to not occur.

I'm embarassed to admit that I've been using git-svn for a few weeks
now and didn't test out these details.  

Here is a patch that I think improves matters a bit:

diff --git a/git-svn.perl b/git-svn.perl
index 4a56f18..daa1764 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -830,6 +830,17 @@ sub commit_diff {
        ($repo, $SVN_PATH) = repo_path_split($SVN_URL);
        $SVN_LOG ||= libsvn_connect($repo);
        $SVN ||= libsvn_connect($repo);
+
+        my ($r_last, $cmt_last) = svn_grab_base_rev();
+        my $fetched = fetch();
+       if ($r_last != $fetched->{revision}) {
+               print STDERR "There are new revisions that were fetched ",
+                               "and need to be merged (or acknowledged) ",
+                               "before committing.\n",
+                               "last rev: $r_last\n",
+                               " current: $fetched->{revision}\n";
+               exit 1;
+       }
        my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
        my $ed = SVN::Git::Editor->new({        r => $SVN->get_latest_revnum,
                                                ra => $SVN_LOG, c => $tb,

But for a possibly busy svn repository, the only real solution is one
that uses the svn libs in a way that behaves like the svn client in
terms of atomicity.