Skip to main content

Merging a branch

This page lists best practices that you need to follow when using the merge operation. These practices are relevant for all types of merges, except when stated otherwise in the particular guideline below.

You should normally always follow these guidelines. Deviating from these guidelines is possible in advanced cases if you are an expert user and know why you are ignoring a particular guideline.

Merge into a clean and updated working copy

Before a merge into a working copy, ensure the following:

  • The working copy must be clean. That is, it must not contain any uncommitted local changes. Running the svn status operation from the root of your working copy must print nothing. If there are any uncommitted local changes, commit them first.

  • The working copy must be updated. Run svn update from the root of your working copy, to ensure that all the files in the working copy are updated to the latest revision (the latest state of this branch).

In TortoiseSVN

In TortoiseSVN, run the Check for modifications command from the root of your working copy, to make sure that the working copy does not contain any local uncommitted changes. If there are any uncommitted local changes, commit them first. Similarly, you need to run the Update command from the root of your working copy.

Merge the source branch in full

You should always merge the whole source branch into the target branch, and should not merge just a part of the source branch. This best practice is known as merging from and to the roots of branches. The goal of this guideline is to avoid a partial (subtree) merge that would record subtree mergeinfo.

For example, suppose that just one subdirectory (e.g. "^/trunk/tests") or even just one file was modified on the trunk. To sync that change into your feature branch, you should still merge the whole trunk directory into the root of your working copy:

C:\Users\Alex\my_work_dir> svn merge "^/trunk"

Note that this also assumes that you properly checked out the working copy, so that the root directory of the working copy (e.g. C:\Users\Alex\my_work_dir) reflects the root directory of the target branch (e.g. "^/branches/my_feature").

In TortoiseSVN

Similarly, in TortoiseSVN, run the Merge command from the root of your working copy. The URL to merge from should be the URL of the root directory of a source branch. For example, the URL to merge from may be https://svn.example.com/MyRepo/trunk.

Make sure you have sufficient repository permissions

To be able to fully merge two branches, you need the following access permissions to the contents of the repository:

  • Read/Write access to all of the target branch. This ensures that when checking out or switching to the target branch, you can get all of its contents (to its full depth) into your working copy. The Write access also ensures that you will be able to commit the merged changes to the target branch.

  • At least Read access to all of the source branch. This ensures that you can merge the whole source branch (to its full depth) into your working copy.

If there are changes eligible for merging at some repository path (subdirectory or file) inside the source branch, but they can’t be merged due to access restrictions, the merge skips that path (notifying you about that) and that path’s changes don’t get merged. This results in a partial (subtree) merge, which may lead to conflicts later.

For example, this can occur if the target path that should receive changes in the working copy is missing (i.e. the working copy does not reflect the whole target branch). Or because you do not have Read access to any paths (subdirectories or files) inside the source branch that contain eligible changes to be merged.

Avoid the ‘2-URL merge’ also called ‘Merge two different trees’

It is recommended that you avoid the fully manual variant of the merge command known as a 2-URL merge, where you specify two URLs instead of one (in addition to an optional working copy target). Although the 2-URL variant gives you the fullest control over what to compare to generate the incoming changes, it introduces the greatest potential for user error.

Instead, in most cases, prefer using the automatic (sync or reintegrate) merge, where you specify just one URL (the URL of the source branch) in the merge command and do not specify the revisions to merge. In more advanced cases, use a single-URL cherrypick merge.

In TortoiseSVN

In TortoiseSVN, this guideline means that you should normally avoid the fully manual 2-URL variant of the merge command, which is called ‘Merge two different trees’ in TortoiseSVN.

Instead, prefer using the ‘Merge a range of revisions’ option. It lets you perform an automatic (sync or reintegrate) merge if you leave the specific range option selected and the field next to it empty, or you select the all revisions option. In most cases you should prefer such an automatic merge.

In more advanced cases, the ‘Merge a range of revisions’ option also lets you perform a single-URL cherrypick merge, if you explicitly specify the revisions to merge from the source branch.

Never resolve a conflict during a reintegrate merge

If any conflicts occur during a reintegrate merge, do not try to resolve them. Instead, cancel the merge by reverting all the changes that it made.

To cancel the merge (to revert all changes), run the following command from the root directory of the working copy: svn revert --recursive .

Switch to the feature branch that you tried to reintegrate, and sync that feature branch with the trunk once more. Typically, a conflict during a reintegrate merge happens if you are trying to reintegrate a feature branch that is not fully synced with the trunk. This occurs if someone has committed newer changes to the trunk after your last sync of that feature branch. Resolve conflicts during the sync on the feature branch. Then, repeat the reintegrate merge.

No conflicts should occur during a successful reintegrate merge.

Do not revert the automatic changes in the svn:mergeinfo property

After merging a different branch into your working copy, do not revert the automatic changes that Subversion has made to the svn:mergeinfo property on the root of the working copy. The only exception when you should revert this change, is if you are completely canceling the merge (reverting all the changes that the merge made).

Seeing the automatically modified mergeinfo

After merging a different branch into your working copy and before you commit the merged changes, you can see the automatic change in svn:mergeinfo as a property-only change on the target path of the merge (on the root directory of your working copy).

For example, consider the following output when running svn status at the root of your working copy:

C:\Users\Alex\my_work_dir> svn status
M .
M README.txt

In this output, the dot . on the first line denotes the current directory my_work_dir (the root of the working copy), while the M on the same first line in the second column indicates a property modification.

In TortoiseSVN

In the TortoiseSVN GUI you can see this as a property change on the root of your working copy:

To view local uncommitted changes in the working copy with TortoiseSVN, right-click in your working copy’s root directory and select TortoiseSVN | Check for modifications.

Do not make unrelated changes during a merge

A merge commit should contain only the changes made by the merge operation itself or changes that you made to resolve conflicts. You should not introduce unrelated changes into the working copy during a merge. For example, if after merging you noticed a typo, you should not fix it in the merge commit. You can correct it later, for example by a separate commit to your feature branch or to the trunk.

Commit the merge in full

Commit all the merged changes that remain after you resolve any conflicts. This guideline ensures that you commit the merged changes together with the mergeinfo describing the merge. If you do not commit the target path into which this merge was done (normally, the working copy’s root directory) and which has its svn:mergeinfo property modified as a result, this modified mergeinfo would not be committed at all.

When using the command-line client, this guideline simply means that you should commit from the root of the working copy and should not explicitly specify individual items that you want to commit:

C:\Users\Alex\my_work_dir> svn commit -m "On my_feature: synced the branch with trunk."

When making a non-merge commit (that does not commit the results of a merge), it is common and normal to do a partial commit, selectively committing only some of the local changes from the working copy. When committing a merge, do not make partial commits like the following:

C:\Users\Alex\my_work_dir> svn commit README.txt -m "Bad practice: this does not commit the branch's root with its modified mergeinfo."

In TortoiseSVN

When using TortoiseSVN, it means that you should commit from the root of the working copy and you must not clear any automatically selected check marks, which show versioned items modified by the merge.

In TortoiseSVN, make sure that you commit only the versioned files modified by the merge, they are automatically selected and their Status may state modified, added or deleted. If the working copy contains unselected files with the non-versioned Status, you should not manually select them and should not include them in the commit.

For example non-versioned files may be temporary files created by your text editor or by your Integrated Development Environment (IDE).

The feature branch should be fully synced before reintegration

Before reintegrating a feature branch into the trunk, the feature branch should be fully synced with the trunk. This means that right before a reintegrate merge of a feature branch into trunk, you should do the final sync merge of changes from trunk into the feature branch.

It allows you to resolve any potential conflicts between trunk and the feature branch while you are still on the feature branch, and lets you commit this conflict resolution to the feature branch. This ensures that this feature branch can be cleanly merged into the trunk without any conflicts, unless the trunk has already received newer commits after the feature branch’s latest sync.

Always use merging to transfer changes between branches

Since a merge brings in changes from another branch, you normally should not recreate the same changes on two branches. This is because when you merge one of these branches into the other, such changes become overlapping changes that occurred independently on these branches. You might need to resolve them as conflicts.

For example, if a new file was added to version control on trunk, the typical way to bring it to your feature branch is by syncing the feature branch with the trunk. Typically, you should not manually paste and add this same file to version control again on your feature branch.

Similarly, if a new paragraph was added to a text file on trunk, you can receive it to your feature branch via a sync merge. Typically, you should not recreate the same change again from scratch on your feature branch.

You might want or need to make such duplicate changes occasionally, but you should not do that as your default workflow. If you aren’t ready to absorb all changes from trunk to your feature branch, consider using the more granular merging method: a cherrypick merge.

Cursory review is sufficient for a sync merge

After performing a sync merge from trunk into a feature branch, it is a common practice to have only a minimal cursory review of the merged changes in the working copy, except for those that caused conflicts.

Subversion will merge changes only if they can be unambiguously merged. You can generally trust that the changes got applied to the correct location. Subversion will merge changes only to the exactly matching path in the target branch. If files within the source or the target branch have been moved or renamed, Subversion detects such moves only by taking into account the historic results of the svn move operation (which is committed as a pair of tracked tree change operations: a tracked copy and a tracked delete of the same item in the same revision). Subversion does not use any heuristics based on the contents of files to detect file renaming or to move files.

Thorough review is needed for a reintegrate merge

After doing a reintegrate merge of a feature branch into the working copy of trunk, the best practice is to do a thorough review of the changes that have been merged to the working copy.

If you are not happy with any of the changes coming from this reintegrate merge, you should not fix them directly in the commit containing the reintegrate merge (see Avoid making unrelated changes in the merge commit above).

In this case, you should normally cancel the merge by reverting all the changes that it made.

To cancel the merge (to revert all changes), run the following command from the root directory of the working copy: svn revert --recursive .

The unsatisfactory changes should be fixed on the feature branch. Then you can repeat the reintegrate merge.