10

Imagine you've got a big SVN tree with branches all over the place. There is the trunk, there are branches, those branches have branches, etc. So, given two branches in the tree, how can you find the common ancestor?

I know that you could simply take the full log and compare it, but it get's kinda slow if your trunk has 75,000 revisions (and most of the time you do compare trunk with another, possibly faraway, branch).

The process will be automated, so you can suggest things which are not done easily by hand.

Added: Forgot to say, I need to get it done in real time. Not in "real time" as in 10ms, but in "real time" as in "before the person waiting for the output gets annoyed". So it'd be nice if it was under 10s.

Vilx-
  • 104,512
  • 87
  • 279
  • 422

4 Answers4

9

I guess this is what you need

svn log -v --stop-on-copy

would return the below

r43477 | username | 2010-09-21 13:19:58 +0530 (Tue, 21 Sep 2010) | 1 line Changed paths: A /trunk/re/XXX (from /branches/release/post_XXX/re/XXX:43476)

From this you can identify that this branch is a ancestor of the current branch. If you combine this the logic mentioned by Victor Nicollet you will be able to get the results in real time.

Version Control Buddy
  • 1,416
  • 10
  • 14
2

Look at the logs at root of the tree. Branching operations will be indicated as copy operations, so you can reconstruct a full ancestor tree of what was copied from where. Leave that code running overnight and you'll have the complete copy tree the next morning, which you can then use to identify common ancestors of your branches.

Next time, you can resume work from the last revision you processed.

Victor Nicollet
  • 24,361
  • 4
  • 58
  • 89
  • Sorry, I need it to be done in as few seconds as possible. :( People will be running it from the command line and waiting for the response. – Vilx- Oct 25 '10 at 14:25
  • Once you have pre-computed the ancestor tree, all the requests for the entire repository should take a few nanoseconds to run. The pre-computation would probably take less time than the actual writing of the program, and it only has to run once. Is there an unmentioned reason why you cannot pre-compute the tree and store it? – Victor Nicollet Oct 25 '10 at 14:30
  • Store it where? Everyone will be running it from their local machines. I suppose I could place it on some common network drive, but I was really hoping for a standalone solution that didn't require any extra resources beyond SVN itself. – Vilx- Oct 25 '10 at 14:33
  • Since your application would be accessing SVN anyway, why not store the ancestor tree file in the repository itself? – Victor Nicollet Oct 25 '10 at 14:44
  • OK, I'll keep this solution in mind, though I'd still vastly prefer something that would do the calculations on the fly. – Vilx- Oct 25 '10 at 14:46
1

It's a bit late for the OP, but I needed the same thing and couldn't find an answer. The following Powershell script works for me.

Basically we fetch a list of revision numbers for each of the paths to be compared (up to an optional revision limit to avoid fetching the entire history), then step through the lists looking for a matching revision number. The lists are naturally sorted in descending revision number order.

param ([string]$path1, [string]$path2, [int]$rev = 0)

if ($path1 -eq "" -or $path2 -eq "") { "Specify two svn paths to compare."; break }

$revs1 = new-object System.Collections.Generic.List``1[System.Int32]
svn log -r HEAD:$rev $path1 | %{ if ($_ -match "^r(\d+)") { $revs1.Add($matches[1]) } }

$revs2 = new-object System.Collections.Generic.List``1[System.Int32]
svn log -r HEAD:$rev $path2 | %{ if ($_ -match "^r(\d+)") { $revs2.Add($matches[1]) } }

$i1 = 0
$i2 = 0

while ($true) {
  if ($revs1[$i1] -eq $revs2[$i2]) { $revs1[$i1]; break }
  elseif ($revs1[$i1] -gt $revs2[$i2]) { do { $i1 += 1} until ($i1 -eq $revs1.Count -or $revs1[$i1] -le $revs2[$i2]) }
  else { do { $i2 += 1} until ($i2 -eq $revs2.Count -or $revs2[$i2] -le $revs1[$i1]) }
  if ($i1 -eq $revs1.Count -or $i2 -eq $revs2.Count) { "No common base revision found - try increasing limit."; break }
}
Ian Horwill
  • 2,957
  • 2
  • 24
  • 24
1

While looking for an equivalent in svn for git merge-base, I hit this post. There's still no simple way around this?

Then here's one possible solution: Clone the repo using git-svn, run git-merge-base providing both braches. Voila!

eftshift0
  • 26,375
  • 3
  • 36
  • 60
  • Branching and merging in svn and git are very different. This will not work for all cases. It would only work for the case where an svn repository has been branched and merged using a specific predictable technique. This is not always the case with svn. – Clintm Nov 22 '16 at 17:58