Resolve Any Conflicts Edit Course

Resolve Any Conflicts

We've already seen how svn status -u can predict conflicts, but dealing with those conflicts is still something that remains to be done. Conflicts can occur any time you attempt to merge or integrate (in a very general sense) changes from the repository into your working copy. By now you know that svn update creates exactly that sort of scenario—that command's very purpose is to bring your working copy up to date with the repository by merging all the changes made since your last update into your working copy. So how does Subversion report these conflicts to you, and how do you deal with them?

Suppose you run svn update and you see this sort of interesting output:

$ svn update
Conflict discovered in 'bar.c'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options:

The U (which stands for “Updated”) and G (for “merGed”) codes are no cause for concern; those files cleanly absorbed changes from the repository. A file marked with U contains no local changes but was updated with changes from the repository. One marked with G had local changes to begin with, but the changes coming from the repository didn't overlap with those local changes.

It's the next few lines which are interesting. First, Subversion reports to you that in its attempt to merge outstanding server changes into the file bar.c, it has detected that some of those changes clash with local modifications you've made to that file in your working copy but have not yet committed. Perhaps someone has changed the same line of text you also changed. Whatever the reason, Subversion instantly flags this file as being in a state of conflict. It then asks you what you want to do about the problem, allowing you to interactively choose an action to take toward resolving the conflict. The most commonly used options are displayed, but you can see all of the options by typing s:



Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: s

  (e)  edit             - change merged file in an editor
  (df) diff-full        - show all changes made to merged file
  (r)  resolved         - accept merged version of file

  (dc) display-conflict - show all conflicts (ignoring merged version)
  (mc) mine-conflict    - accept my version for all conflicts (same)
  (tc) theirs-conflict  - accept their version for all conflicts (same)

  (mf) mine-full        - accept my version of entire file (even non-conflicts)
  (tf) theirs-full      - accept their version of entire file (same)

  (p)  postpone         - mark the conflict to be resolved later
  (l)  launch           - launch external tool to resolve conflict
  (s)  show all         - show this list

Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options:



Let's briefly review each of these options before we go into detail on what each option means.

(e) edit
Open the file in conflict with your favorite editor, as set in the environment variable EDITOR.

(df) diff-full
Display the differences between the base revision and the conflicted file itself in unified diff format.

(r) resolved
After editing a file, tell svn that you've resolved the conflicts in the file and that it should accept the current contents—basically that you've “resolved” the conflict.

(dc) display-conflict
Display all conflicting regions of the file, ignoring changes which were successfully merged.

(mc) mine-conflict
Discard any newly received changes from the server which conflict with your local changes to the file under review. However, accept and merge all non-conflicting changes received from the server for that file.

(tc) theirs-conflict
Discard any local changes which conflict with incoming changes from the server for the file under review. However, preserve all non-conflicting local changes to that file.

(mf) mine-full
Discard all newly received changes from the server for the file under review, but preserve all your local changes for that file.

(tf) theirs-full
Discard all your local changes to the file under review and use only the newly received changes from the server for that file.

(p) postpone
Leave the file in a conflicted state for you to resolve after your update is complete.

(l) launch
Launch an external program to perform the conflict resolution. This requires a bit of preparation beforehand.

(s) show all
Show the list of all possible commands you can use in interactive conflict resolution.



Viewing conflict differences interactively

Before deciding how to attack a conflict interactively, odds are that you'd like to see exactly what is in conflict. Two of the commands available at the interactively conflict resolution prompt can assist you here. The first is the “diff-full” command (df), which displays all the local modifications to the file in question plus any conflict regions:

Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: df
--- .svn/text-base/sandwich.txt.svn-base      Tue Dec 11 21:33:57 2007
+++ .svn/tmp/tempfile.32.tmp     Tue Dec 11 21:34:33 2007
@@ -1 +1,5 @@
-Just buy a sandwich.
+<<<<<<< .mine
+Go pick up a cheesesteak.
+Bring me a taco!
+>>>>>>> .r32

The first line of the diff content shows the previous contents of the working copy (the BASE revision), the next content line is your change, and the last content line is the change that was just received from the server (usually the HEAD revision).

The second command is similar to the first, but the “display-conflict” (dc) command shows only the conflict regions, not all the changes made to the file. Additionally, this command uses a slightly different display format for the conflict regions which allows you to more easily compare the file's contents in those regions as they would appear in each of three states: original and unedited; with your local changes applied and the server's conflicting changes ignored; and with only the server's incoming changes applied and your local, conflicting changes reverted.

After reviewing the information provided by these commands, you're ready to move on to the next action.



Resolving conflict differences interactively

There are several different ways to resolve conflicts interactively—two of which allow you to selectively merge and edit changes, the rest of which allow you to simply pick a version of the file and move along.

If you wish to choose some combination of your local changes, you can use the “edit” command (e) to manually edit the file with conflict markers in a text editor (configured per the instructions in the section called “Using External Editors”). After you've edited the file, if you're satisfied with the changes you've made, you can tell Subversion that the edited file is no longer in conflict by using the “resolve” command (r).

Regardless of what your local Unix snob will likely tell you, editing the file by hand in your favorite text editor is a somewhat low-tech way of remedying conflicts (see the section called “Merging conflicts by hand” for a walkthrough). For this reason, Subversion provides the “launch” resolution command (l) to fire up a fancy graphical merge tool instead (see the section called “External merge”).

If you decide that you don't need to merge any changes, but just want to accept one version of the file or the other, you can either choose your changes (a.k.a. “mine”) by using the “mine-full” command (mf) or choose theirs by using the “theirs-full” command (tf).

Finally, there is also a pair of compromise options available. The “mine-conflict” (mc) and “theirs-conflict” (tc) commands instruct Subversion to select your local changes or the server's incoming changes, respectively, as the “winner” for all conflicts in the file. But, unlike the “mine-full” and “theirs-full” commands, these commands preserve both your local changes and changes received from the server in regions of the file where no conflict was detected.