svnmerge - Subversion merge tracking tool |
*** NOTICE: The information on this page is out of date; please see the svnmerge wiki page for updated information ***
svnmerge is a simple tool that tracks
Subversion branch merges.
It stores the repository path for each merge source ("head") along with the
list of already-merged revisions in the svnmerge-integrated
property associated with the destination ("branch") directory.
You can think of svnmerge as the equivalent of yellow
sticky notes on a subversion branch that record which revisions have
been merged in already from one or more heads, plus some useful
functionality for managing and updating that information.
Features:
Use of the tool is simple:
svnmerge init to intialize merge tracking
on a branch directory.svnmerge avail to review the revisions
available for merging.svnmerge merge to merge in some or all
available revisions.svn commit.
svnmerge is now part of the Subversion source tree in the
contrib/client-side directory.
You can always download the latest version of svnmerge
directly from the Subversion repository,
though the $Keywords$ will not be properly substituted.
Giovanni Bajo has contributed a self-contained Windows executable based on it.
See the Subversion repository for change history.
Use the -f flag with svnmerge init
and svnmerge merge to have svnmerge
create a suitable commit message for you.
Revision lists are specified as comma separated ranges, e.g.,
1412-1419,1423,1427,1433-1440.
Ranges may overlap or be out of order;
svnmerge will automaticaly normalize them. So
1413-1417,1410-1414,1402,1401 is equivalent to
1401-1402,1410-1417.
svnmerge never commits anything; it always leaves that
final step to you. Use svn revert -R . if you need to start over.
Note however that svn revert will not delete any files, so
you may have to remove some files yourself to get a complete reversion.
svnmerge merge requires that there be no outstanding changes in
the branch directory (otherwise you could accidentally "merge" in a change
that never existed in the head directory).
Merges of discontinuous revision ranges can produce conflicts or
omissions; this is an inherent fact of discontinuous merges. For
example, if a revision modifies a file that was created in a previous
revision you haven't merged in yet. Pay attention to the output
from svnmerge (that comes from the svn merge)
for any ignored files or other complaints from subversion;
fixing these cases is up to you. In such cases, it's probably a
good idea to include a comment in the commit message, e.g., ``Note:
patch to foo/bar.c in r1234 not included.''
The help message explains how it works:
$ svnmerge help
Example of a typical merge. This example merges in revision 1436 after reviewing the log message and diffs.
Note that the ``1436'' could have been an arbitrary list of revisions like ``1432-1437,1439,1441-1444''; it doesn't have to be just one as in this example. Nor is it a problem if you specify revisions that are already merged (they will be automatically ignored).
In this example, the new revision 1439 becomes available for merging after the final commit at the bottom. Revision 1439 will be ``empty'' (i.e., contain no changes in the head tree) and it can be merged in whenever, or not; it doesn't matter. Merging in empty revisions helps keep the available revision list smaller and more meaningful, since it will then only include non-empty merge candidates.
$ cd ~/svn/projects/edisplay/branches/1.0-branch
$ svn proplist -v .
Properties on '.':
svnmerge-integrated : /projects/edisplay/trunk:1-1369,1377,1385-1430,1432-1433
$ svnmerge avail
1370-1376,1378-1384,1431,1434-1438
$ svnmerge avail -l -r 1436
------------------------------------------------------------------------
r1436 | archie | 2004-09-27 18:12:33 -0500 (Mon, 27 Sep 2004) | 2 lines
Changed paths:
M /projects/edisplay/trunk/src/java/com/awarix/edsp/client/MainWindow.java
Ensure we create the reconnect timer before we might try to use it.
$ svnmerge avail -d -r 1436
svnmerge: changes in revisions 1436-1436 follow
Index: src/java/com/awarix/edsp/client/MainWindow.java
===================================================================
--- src/java/com/awarix/edsp/client/MainWindow.java (revision 1435)
+++ src/java/com/awarix/edsp/client/MainWindow.java (revision 1436)
@ -1096,6 +1096,9 @
// Set initial status
setStatus("Not connected.");
+ // Create timer for unattended mode auto-reconnection
+ reconnectTimer = new ReconnectTimer();
+
// Display the window
SwingUtilities.invokeLater(new Runnable() {
public void run() {
@ -1121,9 +1134,6 @
numWindows++;
}
- // Create timer for unattended mode auto-reconnection
- reconnectTimer = new ReconnectTimer();
-
// Start reconnect timer
reconnectTimer.start();
}
$ svnmerge merge -r 1436 -f commit.txt
U src/java/com/awarix/edsp/client/MainWindow.java
$ cat commit.txt
Merged revisions 1436 via svnmerge from
http://svn.dellroad.org/svn/eng/projects/edisplay/trunk
$ svn status
? commit.txt
M .
M src/java/com/awarix/edsp/client/MainWindow.java
$ svn diff -N .
Property changes on:
___________________________________________________________________
Name: svnmerge-integrated
- /projects/edisplay/trunk:1-1369,1377,1385-1430,1432-1433
+ /projects/edisplay/trunk:1-1369,1377,1385-1430,1432-1433,1436
$ svn commit -F commit.txt && rm commit.txt
Sending 1.0-branch
Sending 1.0-branch/src/java/com/awarix/edsp/client/MainWindow.java
Transmitting file data .
Committed revision 1439.
$ svnmerge avail
1370-1376,1378-1384,1431,1434-1435,1437-1439
Here's an example of how to set up multi-way merging.
Suppose you have a trunk head and two spin-off branches branch1 and branch2. You want to be able to merge changes in both directions between head and either branch, i.e., bidirectionally between head and branch1 and bidirectionally between head and branch2, but not at all between branch1 and branch2.
$ cd /home/user/myproject/trunk $ svnmerge init -f commit.txt /myproject/branches/branch1 && svn ci -F commit.txt && rm commit.txt Sending trunk Transmitting file data . Committed revision 1533. $ svnmerge init -f commit.txt /myproject/branches/branch2 && svn ci -F commit.txt && rm commit.txt Sending trunk Transmitting file data . Committed revision 1534. $ cd ../branches/branch1 $ svnmerge init -f commit.txt /myproject/trunk && svn ci -F commit.txt && rm commit.txt Sending branch1 Transmitting file data . Committed revision 1535. $ cd ../branch2 $ svnmerge init -f commit.txt /myproject/trunk && svn ci -F commit.txt && rm commit.txt Sending branch2 Transmitting file data . Committed revision 1536.
If you only wanted to merge unidirectionally from the head to the branches, but not in the ``backwards'' direction, then you'd omit the first two steps above.