On Tue, Jun 25, 2013 at 8:33 PM, Tobias Bading <tbad...@web.de> wrote: > I think I can already hear Emacs developers of both VC camps, the Bazaar'ians > and the Git'ians, laughing together in harmony in the distance... ;-) > No disrespect & thank you for the hint, but shouldn't a version control > system be able to answer the question "what's changed?" without making you > jump through hoops?
Yes Git has better behavior here (not sure about Bazaar). Git also has a way to represent tree modifications in their diff format. The problem here is that Subversion's diff isn't really tree versioning aware. This goes back to the fact that when Subversion was written there wasn't a format for representing tree deltas. Git's format has become somewhat of a standard (though even it isn't really sufficient for us). We still don't have a good format for this that's cross VC and the Subversion project never felt like it wanted to take it upon itself to just ship something that couldn't interoperate with others. There were efforts to agree on a format across VC systems, but it was not possible to agree. We probably should have in retrospect just developed a format. Git however, had no choice because their fundamental purpose was to manage passing patches around. Unified diff couldn't solve this problem so they solved it on their own. Subversion being based on a centralized repository didn't have the same requirements of being able to represent every change with diff, so our output favors interoperability with the patch command. Back to your issue. Since Subversion can't represent the copy as part of the diff it tries to do the interoperable thing which is to represent the addition of a new file (from a copy) as an addition. Simply using a revision range isn't exactly what is changing the output you're getting. You can't just use -rM:N where M < N-1, M *MUST* be the revision you copied from. When you specify this then the base of the diff ends up being the file you copied from since Subversion follows the copy and you get the result you want. A great way to see this is to simply add another unrelated file in r1 in your example script and change your diffs to use -c4 and -r1:4. Your copy now comes from r2 and you'll see the same output for both -c4 and -r1:4, where as -r2:4 provides the output you want. >From the perspective of someone who is wanting to see the change done in the repository with diff then I can see your point. From the point of view of someone that wants to send the diff to someone to apply with the patch command that isn't necessarily using Subversion or even the same repository, the way things work now properly are better. Fortunately, the problem I mention above where sending tree changes with the delta should be solved with the --git option to diff (the git people can laugh some more that the solution to your problem should be to pass that option). However, if you use it you'll have the same issues that you have already. Simply because the --git option hasn't really been fully finished being implemented. Subversion doesn't have proper move tracking or even really move heuristics yet, so it can't represent moves. However, it does have fully knowledge of the copy and in this case I would consider it a bug that the --git option does not return the the git extended header as "copy from ..." instead of "new file" as it does now and then provide a diff off the copy. While I understand your interpretation I don't think we are likely to change the default output of diff to behave this way. I can see an argument for an option to diff to tell it to use the base of copies as where they were copied from, but I'm not sure if that's really useful when you'd end up not seeing where it was copied from in the diff. So IMHO the correct solution to this is to fix the --git option and change your vc-svn.el module to pass that flag. That doesn't help you much right now, but I think that's the right solution. The other solutions people have suggested, using log to find the copy from and then setting the range right won't help you with vc-svn.el because if there are multiple files copied from different revs, it will be impossible to get the base correct on all of them. Side note for anyone wondering: Git doesn't track copies, however, when the copy is in the same change then it will always find it. So even without the humorously named --find-copies-harder the equivalent case in Git will always behave as Tobias expects. However, you can end up with similar issues with git when the copy isn't so easy to find (and then you have to start using -C or --find-copies-harder to get the output you expect).