< Development‎ | Tools
Revision as of 19:28, 17 March 2009 by TMG (Talk | contribs) (fill in the "record merges" section)

Jump to: navigation, search

What is svnmerge and why use it?

When you have multiple branches of the same project in SVN, you probably want to keep these branches in sync, at least to a certain extend.

One example of this would be feature branches, i.e. a branch were a bigger feature is developed. You usually want to keep that feature branch in sync with trunk by merging all commits from trunk into that feature branch. Once the feature branch is ready to be merged back to trunk, you want to do just that with as little work as possible.

Another example are the KDEPIM enterprise branches. All changes from the enterprise branches are merged to trunk, but only some changes from trunk are merged back to the enterprise branches.

In both situation, will help you by keeping track of the merges and assisting you in the process of merging.

It has the following useful features:

  • Keeping a list of merged and unmerged commits, so you never forget to merge a single commit
  • Ability to block commits from merging
  • Ability to automatically generate commit messages
  • Support for merging many commits at once
  • Support for multiple branches as merge source
  • Support for bidirectional merges

See also the svnmerge wiki page.

Note that should not be confused with svn merge. The later is a normal SVN command, which is used, among others, by When refering to svnmerge on this page, I always mean Also, when referring to svn merge, I mean the built-in subversion command.

How does it work internally?

svnmerge somehow needs to keep track of which commits are merged and which are not. For this, it uses the SVN properties of the top-level project directory. The properties contain a list with revisions, and that list is updated each time you merge something with svnmerge.

You can view that list with

svn propedit svnmerge-blocked .

and with

svn propedit svnmerge-integrated .

Never change those properties manually!

Installing svnmerge

Download from the svnmerge home page. The trunk version should be fine.

Then, put it into /usr/local/bin and make sure it has executable permissions by issuing

chmod +x /usr/local/bin/

You need to have Python installed, probably with some add-on modules.

Initializing merge tracking for a branch

After creating a new work branch, you need to tell svnmerge about this, so it can set up the initial revision list in the properties. You can skip this section if somebody else already did set up merge tracking for your branches.

To get help in doing so, type help init

After you executed the correct init command, make sure you commit your changes. Only the SVN properties should have changed, type svn status to confirm this.

Afterwards, commit it with

svn ci -F svnmerge-commit-message

Merging Changes

All the svnmerge commands below should be issued in the top-level project working directory, i.e. the directory init was run in. This directory is what I mean with working directory below.

Getting the list of available merges

First of all, you probably want a list of revisions that are not yet merged. This list can be retrieved with svnmerge avail. The avail command supports many options, to get help, type: help avail

Sometimes you already know the revision numbers of the commits you want to merge, in this case you don't need to run svnmerge avail. But be careful, it is easy to forget commits when you don't run this command.

A good practice is get the list of revisions to be merged together with their log message, which often comes in handy. Run the following to store that list in a file: avail --log -b > avail.txt &

Note that the command can take a long time, so we run it in the background with &. Also, svnmerge issues a lot of SVN command in the background, so be sure your passphrase is cached when using svn+ssh, by using ssh-add and ssh-agent.

When you have got multiple branches to merge from, you need to specify the target branch with the -S option. This is the case in the enterprise4 branch, which can merge from the enterprise35 branch or the KDE 4.2.x branch. avail --log -b -S enterprise > avail.txt &

Now, open avail.txt in a text editor. Your goal is now to deal with all revisions in this list, either by merging them, blocking them or marking them as already merged.

Merging commits

Merging a commit is simple: merge [-S enterprise] -r900000

Here, 900000 is a revision number you got from avail.txt, and the name after -S is the branch you want to merge from. You can omit -S if you only have a single branch with merge tracking.

Before typing that command, make sure your working directory is clean, neither the SVN properties nor any files in sub-directories should have any pending changes. Normally, svnmerge will abort if the directories are not clean. Also, your working branch should be up-to-date.

After svnmerge is finished, it will have modified the properties of the working directory, because the properties contain the list of merged revisions, and the revision 900000 was just added to that list. Also, the command has modified your source files, as it merged all changes from the original revision. Nothing is committed yet.

You should now test that the changes actually compile and work as expected, and fix any problems. Sometimes, you'll get conflicts, which you have to resolve manually and then mark as resolved by using svn resolved. After that is done, you can check your changes in.

svnmerge has helpfully created a file named svnmerge-commit-message. You can use that file directly as commit message, or modify its contents. Check in your changes with

svn ci -F svnmerge-commit-message

Congratulations, you have just merged your first commit!

You can also merge multiple revisions at once. But use this with care, it will appear as a single commit, and therefore make svn annotate less useful. Only use this for closely related changes. For this, you can specify a revision list after -r, like: merge [-S enterprise] -r900000,9000002,900004-900010

Blocking commits

Sometimes, you don't want to merge a certain revision, and want that revision to not appear in the avail list at all, for example if the original revision is not useful for the current branch. This can be done by blocking a commit.

Blocking commits has the same syntax as merging: block [-S enterprise] -r900099,9000101,900110-900120

Unlike merging, you should block all revisions you want to block in one go, so you don't create many unnecessary commits.

You should edit svnmerge-commit-message before committing, adding a very brief explanation why you block the commits. Also, add the SVN_SILENT keyword.

Now you can commit your changes with

svn ci -F svnmerge-commit-message

Blocking a commit only changes the SVN properties, no source files are changed (since the goal of blocking the revision is to not merge the source file changes of that revision).

The next time you run avail, the revisions you blocked will not show up there.

Recording merges

Sometimes, it happens that a revision is already merged, but svnmerge doesn't know this. One situation where this happens is if somebody else, who didn't use svnmerge, merged that revision manually. Because the revision was merged manually, the list of merged revisions in the SVN properties was not updated. This means that the commit will show up in avail, although it was already merged.

To fix this situation, you can mark a revision as merged by adding -M to the merge command: merge -M [-S enterprise] -r900099,9000201,900210-900220

This command will add the given revisions to the list of merged commits in the list of the SVN properties.

As with blocking commits, try to record as many merges in a single go as possible. Also, add a short explanation to the commit message, as well as the SVN_SILENT keyword.

To check in your changes, type

svn ci -F svnmerge-commit-message

Problems & Solutions

conflicts on . -> svn resolved + use mergediff to confirm (!) problems with korganizer/views problems with kcal in e3->e4

Helpful Scripts

mergediff mymerge