The basic mechanism Subversion uses to track changesets—that
is, which changes have been merged to which branches—is by recording
data in properties. Specifically, merge data is tracked in the svn:mergeinfo
property
attached to files and directories. (If you’re not familiar with
Subversion properties, now is the time to skim Properties.)
You can examine the property, just like any other:
$ cd my-calc-branch $ svn propget svn:mergeinfo . /trunk:341-390
It is not recommended that you change the value of this property yourself, unless you really know what you’re doing. This property is automatically maintained by Subversion whenever you run svn merge. Its value indicates which changes (at a given path) have been replicated into the directory in question. In this case, the path is /trunk and the directory which has received the specific changes is /branches/my-calc-branch.
There’s also a subcommand, svn mergeinfo, which can be helpful in seeing not only which changesets a directory has absorbed, but also which changesets it’s still eligible to receive. This gives a sort of preview of the next set of changes that svn merge will replicate to your branch:
$ cd my-calc-branch # Which changes have already been merged from trunk to branch? $ svn mergeinfo http://svn.example.com/repos/calc/trunk r341 r342 r343 ... r388 r389 r390 # Which changes are still eligible to merge from trunk to branch? $ svn mergeinfo http://svn.example.com/repos/calc/trunk --show-revs eligible r391 r392 r393 r394 r395
The svn mergeinfo command requires a “source” URL (where the changes would be coming from), and takes an optional “target” URL (where the changes would be merged to). If no target URL is given, it assumes that the current working directory is the target. In the prior example, because we’re querying our branch working copy, the command assumes we’re interested in receiving changes to /branches/mybranch from the specified trunk URL.
Another way to get a more precise preview of a merge operation is
to use the --dry-run
option:
$ svn merge http://svn.example.com/repos/calc/trunk --dry-run U integer.c $ svn status # nothing printed, working copy is still unchanged.
The --dry-run
option doesn’t actually apply any local changes to the working
copy. It shows only status codes that would be
printed in a real merge. It’s useful for getting a
“high-level” preview of the potential merge, for those
times when running svn diff gives too
much detail.
After performing a merge operation, but before committing the
results of the merge, you can use svn diff --depth=empty
to see
only the changes to the immediate target of your merge. If your merge
target was a directory, only property differences will be displayed.
This is a handy way to see the changes to the /path/to/merge/target
svn:mergeinfo
property recorded by the merge
operation, which will remind you about what you’ve just merged.
Of course, the best way to preview a merge operation is to just do
it! Remember, running svn merge isn’t
an inherently risky thing (unless you’ve made local modifications to
your working copy—but we’ve already stressed that you shouldn’t be
merging into such an environment). If you don’t like the results of the
merge, simply run svn revert . -R
to revert the
changes from your working copy and retry the command with different
options. The merge isn’t final until you actually svn commit the results.
While it’s perfectly fine to experiment with merges by running svn merge and svn revert over and over, you may run into some annoying (but easily bypassed) roadblocks. For example, if the merge operation adds a new file (i.e., schedules it for addition), svn revert won’t actually remove the file; it simply unschedules the addition. You’re left with an unversioned file. If you then attempt to run the merge again, you may get conflicts due to the unversioned file “being in the way.” Solution? After performing a revert, be sure to clean up the working copy and remove unversioned files and directories. The output of svn status should be as clean as possible, ideally showing no output.