Next: , Previous: Inodeprints, Up: Advanced Uses


3.6 Merge Conflicts

Several different types of conflicts may be encountered when merging two revisions using the database merge commands merge, explicit_merge, propagate and merge_into_dir or when using the workspace merge commands update, pluck and merge_into_workspace.

The show_conflicts and automate show_conflicts commands can be used to list conflicts between database revisions which would be encountered by the database merge commands. Unfortunately, these commands can't yet list conflicts between a database revision and the current workspace.

In addition, the conflicts set of commands can be used to specify resolutions for some conflicts. The resolutions are stored in a file, and given to the merge command via the --resolve-conflicts-file=filename or --resolve-conflicts option; see See Conflicts.

The merge command normally will perform as many merges as necessary to merge all current heads of a branch. However, when --resolve-conflicts-file is given, the conflicts and their resolutions apply only to the first merge, so the subsequent merges are not done; the merge command must be repeated, possibly with new conflicts and resolutions, to merge the remaining heads.

If conflicts supports resolving a particular conflict, that is the simplest way to resolve it. Otherwise, resolving the different types of conflicts is accomplished by checking out one of the conflicting revisions, making changes as described below, committing these changes as a new revision and then running the merge again using this new revision as one of the merge parents. This process can be repeated as necessary to get two revisions into a state where they will merge cleanly, or with a minimum of file content conflicts.

The possible conflict resolutions are discussed with each conflict in the following sections.

3.6.1 Conflict Types

Monotone versions both files and directories explicitly and it tracks individual file and directory identity from birth to death so that name changes throughout the full life-cycle can be tracked exactly. Partly because of these qualities, monotone also notices several types of conflicts that other version control systems may not.

The two most common conflicts are described first, then all other possible conflicts.

File Content Conflict

This type of conflict is generally the one encountered most commonly and represents conflicting changes made to lines of text within two versions of a single file.

Monotone does not generally use CVS style conflict markers for content conflicts. Instead it makes the content of both conflicting files and the content of their common ancestor available for interactive use during the merge with your favorite merge tool. See the merge3 hook for more information.

Alternatively, rather than using a merge tool it is possible to make further changes to one or both of the conflicting file versions so that they will merge cleanly. This can also be a very helpful strategy if the merge conflicts are due to sections of text in the file being moved from one location to another. Rather than struggling to merge such conflicting changes with a merge tool, similar rearrangements can be made to one of the conflicting files before redoing the merge.

Finally, you can use your favorite merge tool asychronously with the merge, and specify the result file in the conflicts file, using the conflicts command (see Conflicts):

     mtn conflicts resolve_first user filename

Duplicate Name Conflict

A duplicate name conflict occurs when two distinct files or directories have been given the same name in the two merge parents. This can occur when each of the merge parents adds a new file or directory with the conflicting name, or when one parent adds a new file or directory with the conflicting name and the other renames an existing file or directory to the conflicting name, or when both parents rename an existing file or directory to the conflicting name.

In earlier versions of monotone (before version 0.39) this type of conflict was referred to as a rename target conflict although it doesn't necessarily have anything to do with renames.

There are two main situations in which duplicate name conflicts occur:

These conflicts are reported when someone tries to merge the two revisions containing the new files.

Same file

For the first case, the conflict is resolved by dropping one file, using conflicts commands. The contents should be manually merged, in case they are slightly different. Typically, a user will have one of the files in their current workspace; the other can be retrieved via automate get_file_of; the revision id is shown in the merge error message. The process can be confusing; here's a detailed example.

Suppose Beth and Abe each commit a new file checkout.sh. When Beth attempts to merge the two heads, she gets a message like:

     mtn: 2 heads on branch 'testbranch'
     mtn: [left]  ae94e6677b8e31692c67d98744dccf5fa9ccffe5
     mtn: [right] dfdf50b19fb971f502671b0cfa6d15d69a0d04bb
     mtn: conflict: duplicate name 'checkout.sh'
     mtn: added as a new file on the left
     mtn: added as a new file on the right
     mtn: error: merge failed due to unresolved conflicts

The file labeled right is the file in Beth's workspace. To start the conflict resolution process, Beth first saves the list of conflicts:

     mtn conflicts store

In order to merge Beth's and Abe's file versions, Beth retrieves a copy of Abe's file:

     mtn automate get_file_of checkout.sh \
     --revision=ae94e6677b8e31692c67d98744dccf5fa9ccffe5 \
     > _MTN/resolutions/checkout.sh-abe

Now Beth manually merges (using her favorite merge tool) checkout.sh and _MTN/resolutions/checkout.sh-abe, leaving the results in _MTN/resolutions/checkout.sh-merge (not in her copy).

Then Beth specifies the conflict resolution, and finishes the merge:

     mtn conflicts resolve_first_left drop
     mtn conflicts resolve_first_right user _MTN/resolutions/checkout.sh-merge
     mtn merge --resolve-conflicts-file=_MTN/conflicts
     mtn conflicts clean
     mtn update

When Abe later syncs and updates, he will get the merged version.

Different files

The second case, where two different files accidently have the same name, is resolved by renaming one or both of them.

Suppose Beth and Abe each start working on different thermostat models (say Honeywell and Westinghouse), but they both name the file thermostat. When Beth attempts to merge, she will get the same error message as in the first case. When she retrieves Abe's file, she will see that they should be different files. So she renames her file, merges, and updates:

     mtn conflicts store
     mtn conflicts resolve_first_left rename thermostat-westinghouse
     mtn conflicts resolve_first_right rename thermostat-honeywell
     mtn merge --resolve-conflicts-file=_MTN/conflicts
     mtn conflicts clean
     mtn update

Now she has her file in thermostat-honeywell, and Abe's in thermostat-westinghouse.

Missing Root Conflict

Monotone's merge strategy is sometimes referred to as die-die-die merge, with reference to the fact that when a file or directory is deleted there is no means of resurrecting it. Merging the deletion of a file or directory will always result in that file or directory being deleted.

A missing root conflict occurs when some directory has been moved to the root directory in one of the merge parents and has been deleted in the other merge parent. Because of die-die-die merge the result will not contain the directory that has been moved to the root.

Missing root conflicts should be very rare because it is unlikely that a project's root directory will change. It is even more unlikely that a project's root directory will be changed to some other directory in one merge parent and that this directory will also be deleted in the other merge parent. Even still, a missing root directory conflict can be easily resolved by moving another directory to the root in the merge parent where the root directory was previously changed. Because of die-die-die merge, no change to resolve the conflict can be made to the merge parent that deleted the directory which was moved to the root in the other merge parent.

See the pivot_root command for more information on moving another directory to the project root.

conflicts does not yet support resolving this conflict.

Invalid Name Conflict

Monotone reserves the name _MTN in a workspace root directory for internal use and treats this name as illegal for a versioned file or directory in the project root. This name is legal for a versioned file or directory as long as it is not in the project root directory.

An invalid name conflict occurs when some directory is moved to the project root in one of the merge parents and a file or directory that exists in this new root directory is renamed to _MTN or a new file or directory is added with the name _MTN to this directory in the other merge parent.

Invalid name conflicts should be very rare because it is unlikely that a project's root directory will change. It is even more unlikely that a project's root directory will change and the new root directory will contain a file or directory named _MTN. Even still, an invalid name conflict can be easily resolved in several different ways. A different root directory can be chosen, the offending _MTN file or directory can be renamed or deleted, or it can be moved to some other subdirectory in the project.

See the pivot_root command for more information on moving another directory to the project root.

conflicts does not yet support resolving this conflict.

Directory Loop Conflict

A directory loop conflict occurs when one directory is moved under a second in one of the merge parents and the second directory is moved under the first in the other merge parent.

Directory loop conflicts should be rare but can be easily resolved by moving one of the conflicting directories out from under the other.

conflicts does not yet support resolving this conflict.

Orphaned Node Conflict

An orphaned node conflict occurs when a directory and all of its contents are deleted in one of the merge parents and further files or directories are added to this deleted directory, or renamed into it, in the other merge parent.

Orphaned node conflicts do happen occasionally but can be easily resolved by renaming the orphaned files or directories out of the directory that has been deleted and into another directory that exists in both merge parents, or that has been added in the revision containing the orphaned files or directories.

conflicts does not yet support resolving this conflict.

Multiple Name Conflict

A multiple name conflict occurs when a single file or directory has been renamed to two different names in the two merge parents. Monotone does not allow this and requires that each file and directory has exactly one unique name.

Multiple name conflicts do happen occasionally but can be easily resolved by renaming the conflicting file or directory in one or both of the merge parents so that both agree on the name.

conflicts does not yet support resolving this conflict.

In earlier versions of monotone (those before version 0.39) this type of conflict was referred to as a name conflict.

Attribute Conflict

An attribute conflict occurs when a versioned attribute on a file or directory is set to two different values by the two merge parents or if one of the merge parents changes the attribute's value and the other deletes the attribute entirely.

Attribute conflicts may happen occasionally but can be easily resolved by ensuring that the attribute is set to the same value or is deleted in both of the merge parents. Attributes are not merged using the die-die-die rules and may be resurrected by simply setting their values.

conflicts does not yet support resolving this conflict.