Taming the SVN Merge: Understanding svn:mergeinfo and the Cost of Cherry-Picking
Subversion tracks branch integration with svn:mergeinfo. Learn how merge tracking avoids double-merges, when cherry-picking creates property bloat, and how to safely inspect and dry-run a merge before committing.
27 Sept 2025, 04:42 UTC

The double-merge problem you can avoid with mergeinfo
In a long-lived branching workflow the most annoying failure is a redundant merge. You cherry-pick a hotfix from a feature branch into trunk, then later merge the whole feature branch and Subversion tries to apply that same fix again. Without a memory of what was already integrated the system treats the second attempt as a new change and forces manual resolution of work you already approved.
The useful takeaway is that Subversion 1.5+ does not rely on file state alone. It records integration history in svn:mergeinfo, a property stored on directories, so a merge can skip revisions that are already accounted for.
How svn:mergeinfo records integration history
Automatic merge tracking was introduced in SVN 1.5. When you merge, the client identifies the common ancestor of source and target and then consults svn:mergeinfo on the target directory to determine which revision ranges have already been merged from that source path.
The property is a list such as /branches/feature-x:100-150. That means revisions 100 through 150 from that source have been merged into the directory that holds the property. On the next merge Subversion applies only the delta between the last recorded range and the current head of the source.
Because the metadata lives on directories, merges can be scoped. A common engineering decision is subdirectory merges, pulling changes from a specific sub-tree rather than the entire project root, to keep branches clean and reduce noise.
Cherry-pick versus full branch merge
Engineers regularly choose between merging an entire branch and cherry-picking specific revisions. Both update svn:mergeinfo, but the shape of the metadata differs.
- Full branch merges create contiguous ranges, e.g. /branches/feature-x:100-150. This is easier for the client to parse and is the most performant pattern for ongoing integration.
- Cherry-picking records individual revisions, e.g. /branches/feature-x:102,105,110. It is useful for hotfixes, but repeated cherry-picks fragment the property.
Fragmentation leads to property bloat. In very large projects with hundreds of cherry-picked revisions across many subdirectories, the mergeinfo string can grow large enough that operations like svn update or svn status slow as the client parses extensive metadata. Manual editing of svn:mergeinfo is also risky; corrupting the history can cause persistent merge conflicts in future operations.
Worked example: inspect and dry-run a merge
Before changing a production branch, verify what Subversion thinks needs to be merged.
Inspect current merge history
Run from the root of a working copy checked out from the target branch. Read permission on the repository is required.
svn prop-get svn:mergeinfo .The command shows the recorded ranges for that directory and its descendants. Use it to confirm whether earlier cherry-picks are already recorded.
Simulate the merge
From the root of the working copy on the target branch, run a dry-run. No write permission is needed for the simulation, only read access to source and target.
svn merge ^/branches/feature-x --dry-runThe dry-run calculates the merge based on svn:mergeinfo and the common ancestor, and reports which revisions would be applied without modifying files. If the output lists revisions you know were already merged, the mergeinfo is likely out of sync. If it lists only new changes, removing --dry-run and committing will record the new range in svn:mergeinfo.
Risks to note: a dry-run does not resolve tree conflicts. If a file was renamed in the target and edited in the source, Subversion will report a tree conflict that requires manual resolution during the actual merge-commit phase.
Limitation: tree conflicts are not automatic
Merge tracking handles content changes well but struggles with structural changes. A tree conflict occurs when svn:mergeinfo expects a change to a path that has been moved or deleted in the target.
For example, renaming utils.c to network_utils.c on trunk while a branch edits utils.c creates a mapping problem. Subversion cannot automatically apply the branch edit to the renamed file, so you must manually decide whether the rename or the edit takes precedence and then commit the resolution.
Large-scale merges with thousands of revisions can also degrade client performance because the merge calculation must parse extensive metadata across the tree.
Actionable closing
Prefer full branch merges over repeated cherry-picks when possible, and keep merges scoped to subdirectories when the change set is localized. Always inspect svn:mergeinfo before a merge and use --dry-run to confirm the delta. Never edit svn:mergeinfo by hand, and resolve tree conflicts immediately after they appear to avoid hidden drift between branches.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.