reset password

2. Merge

A version control system like Subversion allows the members of a group project to work on different branches of the project. The good news is that they can work on the project at the same time without interfering with each other, but the downside is that the changes made by each member are not automatically shared by others. This is where the merge operation comes in, which, in a sense, copies changes between different branches of a project.

In this section, we first explain the semantics of the merge operation in Subversion, then discuss several merge scenarios that are common in a group project setting.

2.1 The Semantics of Merge in Subversion

The merge operation in Subversion take two parameters, a Source URL (a.k.a From URL or Start URL), and a Target URL (a.k.a. To URL or End URL):

svn merge SourceURL TargetURL

The semantics of the merge operation is the following:

Compare the version of the project represented by the source URL and the version represented by the Target URL, calculate the changes needed to transform the source version to the target version, and apply these changes to the working copy.

There are several things worth noting here.

First of all, when people look at terms like Source URL and Target URL, they tend to think that the changes come from the source version and will be copied to the target version. However, in Subversion it is actually the opposite - the target version has the changes the source version wants. The terms source and target (or from and to) refer to the states of the project before and after the changes are applied, not the source and the target of the changes themselves.

Secondly, note that the changes (i.e. differences) bwteeen the source and the target version are applied to the working copy, not the branch in the repository. In other words, nothing changes in the repository after a merge until you perform a commit operation.

Thirdly, a URL in Subversion is the combination of a repository location and a revision number. When the revision number is not specified, by default it is assumed to be the latest revision at the repository location, which is known as the HEAD revision. Sometimes you might want to extract the changes between two revisions at the same repository locations, and in those case you must specify the revision number explicitly, for example:

svn merge svn://cs3/hello/branches/StudentA-branch@2 svn://cs3/hello/branches/StudentA-branch@3

In this example Subversion would extract the changes between Revision 3 and Revision 2 at the repository location svn://cs3/hello/branches/StudentA-branch and apply these changes to the working copy.

2.2. Preparation Before Merge

Merge can be a little tricky, and to make the process as smooth as possible, a little preparation before merge is recommended.

First, commit all local changes and make sure the working copy is up to date. Specifically, if the working copy has local changes, perform a commit operation; if the working copy has no local changes, perform an update operation.

Second, take a look at the changes to be merged before doing the merge. For example, suppose Student A made some changes to the HelloWorld class and committed the changes, and Student B wants to
get the changes to his or her working copy. Before doing the merge, Student B can examine the changes made by Student A as follows:

  • In Eclipse, select the SVN Repository Exploring Perspective.
  • Right click on Student A's branch (i.e. /branches/StudentA-branch) and select Show History. The revision history of Student A's branch will be displayed in the History tab as shown in Figure 2.2.1.

[History of Student A's Branch]

Figure 2.2.1 Revision History of Student A's Branch

The revision history shows the list revisions at the repository location /branches/StudentA-branch. Selecting a revision in the list will reveal further details about the revision. For example, when Revision 5 is
selected, it shows that HelloWorld.java was modified in this revision. To see exactly what changes were made to HelloWorld.java, right clik on the file and select Compare.... A Window will popup asking for the
revision numbers to compare. Note that the revison of HelloWorld.java prior to Revision 5 is Revision 3, so select 3 and click OK, and Eclipse will show a side-by-side comparison of the two revisions.

A screen capture video illustrating this process is available here.

2.3 Common Merge Scenarios

We now discuss three common merge scenarios. In all three cases we assume that both Student A and B start with the same version of the project in their branches.

2.3.1 Changes on One Side

Suppose Student A made some changes to HelloWorld.java and committed them to the repository, and Student B wants to copy these changes to his or her branch. We call this scenario Changes on One Side.

In Eclipse, Student B can right click on the project and select Team -> Merge. The Merge screen will pop up asking Student B to enter the source and the target URL for the merge.

Note that in this case, Student B has not made any changes, so to extract the changes made by Student A, we can simply take the differences between StudentA-branch and StduentB-branch, as shown in Table 2.3.1.1.

  Repository Location
Revision
Source URL
svn://cs3.calstatela.edu/branches/StduentB-branch
HEAD
Target URL
svn://cs3.calstatela.edu/branches/StduentA-branch
HEAD

Table 2.3.1.1 Source and Target URLs for Merge Scenario #1

After the merge, the changes made by Student A will be applied to the working copy of Student B, as shown in Figure 2.3.1.1. Student B can then commit the changes to his or her branch.

[Source and Target URLs for Merge Scenario #1]

Figure 2.3.1.1 Merge Scenario #1 - After Merge

A screen capture video illustrating this process is available here.

2.3.2 Non-conflicting Changes on Both Sides

Suppose Student A added a new class Foo, while Student B added a new class Bar, as shown in Figure 2.3.2.1. Note that these two classes are in different files under differnt folders, so they do not conflict with each other. We call this scenario Non-conflicting Changes on Both Sides.

[Merge Scenario #2 - Before Merge]

Figure 2.3.2.1 Merge Scenario #2 - Before Merge

Let's first consider how Student B can copy the changes made by Student A. If we use the same source and target URL as in the first scenario, we would notice that changes made by Student B (i.e. the Bar class) will be removed, and this is certainly not what we want. We note that unlike the first scenario, in this case we do not want to transform StudentB-branch into StudentA-branch; instead, we simply want to copy over the changes made by Student A, so the question becomes how do we extract these changes? Based on the semantics of merge, the answer is quite simple: they are simply the differences between the two revisions of StudentA-branch before and after the changes.

  Repository Location
Revision
Source URL
svn://cs3.calstatela.edu/branches/StduentA-branch The revision before the changes were committed
Target URL
svn://cs3.calstatela.edu/branches/StduentA-branch HEAD (i.e. the revision where the changes were committed)

Table 2.3.2.1 Source and Target URLs for Merge Scenario #2

Table 2.3.2.1 shows the source and target URLs that should be used in this scenario, and the results of the merge is shown in Figure 2.3.2.2.

[Merge Scenario #2 - After Merge]

Figure 2.3.2.2 Merge Scenario #2 - After Merge

To copy Student B's changes, Student A can perform a similar merge operation with the source and target URLs being two revisions of StudentB-branch.

A screen capture video illustrating this process is available here.

2.3.3 Conflicting Changes on Both Sides

Suppose both Student A and Student B made changes to HelloWorld.java, and we call this scenario Conflicting Changes on Both Sides.

To copy changes from Student A, Student B can perform a merge operation with the same source and target URLs as shown in Table 2.3.2.1. However, because both students have modified HelloWorld.java, this merge operation will lead to a conflict, as shown in Figure 2.3.3.1.

[Merge Conflict]

Figure 2.3.3.1 Merge Conflict

Note that when a conflict happens, Subversion will do several things:

  • The source file will be modified to include all the conflicting changes with additional markers indicating which change comes from which revision.
  • Three versions of the conflicting file will be created  - the working copy, the version from the source URL (i.e. merge-left) and the version from the target URL (i.e. merge-right). This allows the developer to examine and compare these different versions before making a decision. These files will be automatically removed after the conflict is marked as resolved (see below).
  • The Console View shows the names of the conflicting files and the total number of conflicts in the merge.

To resolve the conflict, Student B can manually edit HelloWorld.java, then right click on the file name and select Team -> Mark Resolved.

[Mark Resolved Screen]

Figure 2.3.3.2 Mark Resolved Screen

The Mark Resolved screen is shown in Figure 2.3.3.2. Since Student B manually edited the source file to resolve the conflict, the first option is selected. Note that instead of manually editing the source file, one can also resolve a conflict at this screen by simply choosing which version of the file to keep.

After the conflict is resolved, Student B can commit the changes as usual.

A screen capture video illustrating this process is available here.

2.4 Summary

Merge simply extracts the differences between two revisions represented by the source and the target URL, and apply these differences to a working copy. The key of a merge is to identify the proper source and target URLs.

The complexity of merge comes from the conflicts. To avoid excessive conflicts, merge should be done regularly between two actively developed branches, i.e. do not wait until they grow too far apart.
 

This page has been viewed 3262 times.