wiki:UmTutorial/ResolvingConflicts

Resolving Conflicts in UM FCM

Before proceeding ensure you have completed the Setting Up , Running UM FCM jobs and Making Code Changes sections of the tutorial.


Introduction and Merging

Introduction

This tutorial is designed to give you a little experience with the various ways you can use xxdiff (the FCM merge tool) to resolve conflicts as the result of a merge. It can, of course, only provide a limited set of examples, but these should be representative of what can be achieved.

Merging

In the code changes tutorial you had an introduction to merges and conflicts. It might be worth reviewing this before you go any further.

For the purposes of this tutorial, 2 branches have been set-up so you can merge one into the other and resolve the conflicts that result. They are fcm:um_tutorial_br/dev/ros/VN7.0_branch_one and fcm:um_tutorial_br/dev/ros/VN7.0_branch_two.

We wish to take VN7.0_branch_one as our base code and merge VN7.0_branch_two into it. To do this, you can either checkout VN7.0_branch_one by typing

fcm checkout fcm:um_tutorial_br/dev/ros/VN7.0_branch_one

or, if you have a pre-existing UM tutorial working copy you can cd into this and type

fcm switch fcm:um_tutorial_br/dev/ros/VN7.0_branch_one

to switch the working copy to the branch. Your working copy should now contain a copy of the VN7.0_branch_one branch. You can confirm this by changing directory to the top level of your working copy and typing

fcm info

to which you should get something similar to the following

ros@puma$ fcm info
=> svn info
Path: .
URL: svn://puma/UM_TUTORIAL_svn/UM/branches/dev/ros/VN7.0_branch_one
Repository Root: svn://puma/UM_TUTORIAL_svn
Repository UUID: 128fe4f4-ca53-0410-8b5d-f5eaa65b2c12
Revision: 1056
Node Kind: directory
Schedule: normal
Last Changed Author: ros
Last Changed Rev: 1041
Last Changed Date: 2008-10-29 11:02:28 +0000 (Wed, 29 Oct 2008)

Note the URL points to the VN7.0_branch_one.

Now we can perform the merge. To do this, check you are in the top-level directory of the working copy and then type

fcm merge fcm:um_tutorial_br/dev/ros/VN7.0_branch_two

and you should be greeted by the following,

Available Merges From /UM/branches/dev/ros/VN7.0_branch_two: 1057 1043 1042
Please enter the revision you wish to merge from (or just press <return> for "1057"):

You will note that you are offered the option of choosing the revision of the branch that you wish to merge into your working copy. The version we want for this tutorial is the most recent (1057), so just press return. This gives the following message,

About to merge in changes from /UM/branches/dev/ros/VN7.0_branch_two@1057 compared with /UM/trunk@1018
This merge will result in the following changes:
--------------------------------------------------------------------------------
C    src/control/top_level/veg_ctl.F90
C    src/control/mpp/file_open.F90
C    src/atmosphere/land_surface/pdm.F90
--------------------------------------------------------------------------------
Would you like to go ahead with the merge?
Enter "y" or "n" (or just press <return> for "n"): 

This tells you that the 3 named files will be updated, and that all 3 of them will result in conflicts (the C in the first column indicates this). You are asked if you wish to continue with the merge and pressing n will result in aborting the merge and leaving your working copy untouched. In this case however, we do wish to continue, so type y. This then gives the following message,

Performing merge ...
C    src/control/top_level/veg_ctl.F90
C    src/control/mpp/file_open.F90
C    src/atmosphere/land_surface/pdm.F90

and you are reminded of the files that have been updated and the fact they are in conflict!

Using the command

fcm status

at this point will give the following information

ros@puma$ fcm status
=> svn status
?      src/control/top_level/veg_ctl.F90.merge-left.r1018
?      src/control/top_level/veg_ctl.F90.merge-right.r1057
?      src/control/top_level/veg_ctl.F90.working
C      src/control/top_level/veg_ctl.F90
?      src/control/mpp/file_open.F90.working
?      src/control/mpp/file_open.F90.merge-right.r1057
?      src/control/mpp/file_open.F90.merge-left.r1018
C      src/control/mpp/file_open.F90
?      src/atmosphere/land_surface/pdm.F90.working
?      src/atmosphere/land_surface/pdm.F90.merge-right.r1057
?      src/atmosphere/land_surface/pdm.F90.merge-left.r1018
C      src/atmosphere/land_surface/pdm.F90

This tells us that the 3 files have been updated and are in conflict, and that FCM has introduced a number of temporary files (3 for each file in conflict) that will be needed by the system when we resolve the conflicts - we don't need to know what is in the files at this stage.

At this point we have completed the merge, but our working copy isn't usable due to the conflicts so the next stage is to resolve these. Remember throughout this process that merges and conflict resolution are performed in a working copy so if you stuff things up really badly you can either use

fcm revert -R .

to go back to a pristine working copy or just delete the working copy and start again!


Conflict Resolution Introduction

The FCM command for resolving conflicts is fcm conflicts. If you specify it without any arguments, it will run through all the files that are in conflict consecutively. Alternatively, if you wish to choose the order of the files you wish to resolve conflicts in, you can use fcm conflicts <filename> to specify the file. Normally the first approach is used as the order doesn't matter, but this tutorial will use the second approach to ensure the tasks are in the right order!

The tool used for resolving conflicts is xxdiff. This is the same tool that is used by FCM for showing differences, but when used for resolving conflicts it has different menu choices and a different appearance. This section of the tutorial will explain what the different panels mean so we can do exercises with it later.

The following screengrab is typical of the sort of display that xxdiff will provide

xxdiff.gif

Number of Unresolved Conflicts. The figure in the top-right corner (circled in dashed blue for this example only) indicates the number of unresolved conflicts remaining. When resolving conflicts the aim is to get this number down to 0.

Left Panel. The left panel contains the working copy from before the merge. Thus in our example it will contain the code in VN7.0_branch_one.

Right Panel. The right panel contains the code that is being merged in. So, in our examples it will contain the code in VN7.0_branch_two.

Middle Panel. The middle panel contains the so called common ancestor. Inthe common case that both branches are from the same point of the trunk, this will be the trunk at the point the branch was made. In other words, the middle panel shows the code before anyonestarted making changes. This can be useful as it shows where both changes started from and can help in working out exactly what was done by each change.

Green Highlight. Lines highlighted in green are unselected. This isthe default colour - it can be customised in your $HOME/.xxdiffrc file.

Purple Highlight. Lines highlighted in purple are selected. Again a default that can be customised.

Hatched Background. Lines that have a hatched background don't really exist. They are there as a 'blank alternative' to the lines in the other panels.

Navigation. You are probably aware from using xxdiff as a differencing tool that you can use keyboard shortcuts to navigate the file. This is also true when resolving conflicts,

  • n Next Difference (also View -> Next difference)
  • p Previous Difference (also View -> Previous difference)
  • b Next Unresolved Conflict (also View-> Next unresolved)
  • o Previous Unresolved Conflict (also View-> Previous unresolved)

The latter two options are the most useful when resolving conflicts.

Merged view. The menu item Windows -> Toggle popup merged view will give you a new window that shows the result of the merge that updates interactively as you make selections. Alternatively Windows -> Toggle pane merged view will add a new panel at the top that interactively shows the merged code.

The Aim. The aim of resolving conflicts is to ensure one block (from the left, right or middle panels) is selected for each difference. xxdiff will have done all the obvious ones for you (i.e. where changes are not on the same lines) and the only ones left to do are the awkward ones! Note that you can select a block by using the left mouse button.


Using Split/Swap/Join?

OK - so much for the theory! Now it is time to try some real conflict resolution. The first example is where two changes have been made in the same place and we want to keep all of both changes, but making sure we get them in the right order. To get going, type

fcm conflicts src/control/mpp/file_open.F90

and you should get a xxdiff window. Type b to get to the first unresolved conflict and you should see the following:

splitswapjoin_1.gif

We can see that there is just one unresolved conflict in this file and it is where we have 2 history comments added. We wish to keep both of these and ensure that the vn6.6 comment comes before the vn7.0 comment.

This is where the 'Split/Swap/Join?' command comes in. It can be found either under the menu Region -> Split/Swap/Join? or by using the s key shortcut. Using this option will split the current region into two. Using the command again will swap the order of the two regions, and using it a third time will go back to the original single region. For more complicated changes, the split may be into more regions and subsequent uses of the command will cycle through all possible orderings before finally re-joining them into the original region.

To get the result we neeed this time, use Split/Swap/Join? twice to get the change comment in the right-hand panel first and the change comment in the left-hand panel second. Then use the left mouse button to select both the change comments. You should notice that the remaining conflicts number in the top-right corner has become 0. If you've done this correctly, you should have the following situation:

splitswapjoin_2.gif

Once you are sure you've got the correct resolution of the conflict (you may wish to use the Merged View to check), we can exit xxdiff by using the File -> Exit with MERGED command (or m keyboard shortcut). This tells FCM that the merge has been successful. If you have made a mistake and want to abandon your attempt at conflict resolution,you can use File -> Exit with REJECT (or r shortcut).

Once you've resolved the conflicts FCM will give you the following text

You merged all the changes.
Would you like to run "svn resolved"?
Enter "y" or "n" (or just press <return> for "n"): y

Enter y if you are convinced you've resolved the conflict correctly and you should be given the following message:

Resolved conflicted state of 'file_open.F90'

Congratulations - you have resolved your first awkward conflict!


Using middle-mouse button line selection

Having learned a technique for using xxdiff for conflict resolution we can use this in conjunction with a new technique for more difficult conflicts. In your working copy, type:

fcm conflicts src/control/top_level/veg_ctl.F90

and then in xxdiff type b to go to the first uresolved conflict. You should see the following situation:

splitswapjoin_3.gif

Firstly, I apologise for the variable names and syntax errors!

You can see that in VN7.0_branch_one(i.e. the left panel) 3 new arguments were added to the argument list, new_argument1, new, newer after the DIM_CS1, DIM_CS2 arguments. In the other branch, VN7.0_branch_two (i.e. the right panel) 3 other arguments have been added. In this case, wibble, wobble were added before the global_row_length, global_rows arguments and arg_2 added after these.

It is clear that we want our final argument list to be (with appropriate continuations)

wibble, wobble,
global_row_length, global_rows, arg_2
DIM_CS1, DIM_CS2,new_argument1
new,newer

This is actually a fairly difficult conflict to resolve and you might find the Merged view rather handy in making sure you've got the right solution!

To start with we need to have some options of which code to choose. Split/Swap/Join? is again the tool of choice for this. In this case Split/Swap/Join? will split the conflict into 3 sections and thus there are 6 potential orders that the sections could have. In this case we need to make sure that the blocks are ordered correctly for the newly introduced variables to be in the correct order. Using Split/Swap/Join? a total of 5 times (you might appreciate the shortcut s at this point!) should give you the following:

splitswapjoin_4.gif

Now we have the blocks in the right order, we need to select the code we need. Unfortunately, some code is repeated in each of the blocks, so choosing code at a block level isn't enough. The middle mouse button however can be used to select individual lines. Thus to get the correct code in this case we need to

  • Use the middle mouse button to select the wibble, wobble line from the right panel,
  • Use the middle mouse button to select the global_row_length, global_rows, arg_2 line from the right panel,
  • Use the middle mouse button to select the DIM_CS1, DIM_CS2, new_argument1 line from the left panel,
  • Use the middle mouse button to select the new, newer line from the left panel

At this point, we have chosen all the code we need, but the Conflict Remaining indicator in the top-right corner of xxdiff shows we have 3 conflicts remaining. These are the lines still coloured green. To get rid of these use the middle mouse button to click on hte panel that has hatched backgrounds (rather than code). This ensures that nothing (not even a blank line) is selected rather than code for these lines. The next screenshot shows the hatched lines you need to click on in a light red. The red will not be in your xxdiff window - this is just for illustrative purposes.

splitswapjoin_5.gif

When you've done the selections correctly, you should have the following:

splitswapjoin_6.gif

Once you've done this, you can use File -> Exit with MERGED (or shortcut m) and answer y to the request to run svn resolved as you did for the previous case. Once this is complete, you'll have resolved the second conflict!


Editing a file to resolve conflict

We've seen that a few clicks can resolve some fairly awkward conflicts, but there are some situations that it is impossible to resolve in such a way and for which you'll need to edit one of the files involved. You can do this from within xxdiff and this section will show you how.

Before we start, however, we need to make sure xxdiff is set up to use the editor of your choice. By default, xxdiff will use the editor that is specified in your $EDITOR environment variable. Note that this needs to be an editor that will display in its own window (so gvim -f is OK, but vi isn't). If $EDITOR specifies the editor you wish to use, all is OK. If not, you can either set this variable (e.g. by typing export EDITOR=nedit) or you can set the variable in the xxdiff options file. To do the latter, you will need to create (or edit if it already exists) the $HOME/.xxdiffrc file and add a line to specify the editor. Examples might be:

  • Command.Edit: "nedit"
  • Command.Edit: "gvim -f"
  • Command.Edit: "emacs"

The final conflict to resolve can be set up by typing

fcm conflicts src/atmosphere/land_surface/pdm.F90

in your working copy. Using b to go to the unresolved conflict, you will see the following:

splitswapjoin_7.gif

Note the VN7.0_branch_one has added the argument NEW_1 to a line and that VN7.0_branch_two has added the argument NEW_2 to the same line. Clearly to resolve the clash we need both arguments included in a particular order (we'll assume NEW_1 comes before NEW_2 in this case!). This conflict can't be split as it is on a single lines so none of the tools we've used previously will help. The only way to resolve it is to edit one of the files. xxdiff provides the ability to launch an editor on one of the files. The best file to choose is the one that will require fewest changes - in this case it doesn't matter, so we'll edit the left one arbitarily.

The File -> Edit left file menu will launch an editor with a copy of the left file in it (remember this corresponds to the working copy - hence VN7.0_branch_one in this case). Edit the line with the new argument on it to add NEW_2,. The line should now read:

    &             NPNTS,SOIL_PTS,SOIL_INDEX,NSHYD,NEW_1,NEW_2,        &

Then save and exit your editor in the normal way.

You'll not see any difference in xxdiff at this stage as it is still working with the previous version of the file. Using File -> Redo diff will re-compute the difference map and you will see that the edited version of the file is being used.

Unfortunately, redoing diffs will get rid of any automatically resolved conflicts, so the Unresolved Conflict indicator in the top-right corner will be 3. You now need to re-do the automatic conflict resolution by using the Global -> Merge menu item. After doing this, only 1 unresolved conflict will be left, which is the line we had previously edited. Clicking the region in the left panel will choose our edited version to complete resolving the conflicts.

Remember to File -> Exit with MERGED and to answer y to run svn resolved

At this stage you should have resolved all the conflicts and

fcm status

should give you

=> svn status
M      src/control/top_level/veg_ctl.F90
M      src/control/mpp/file_open.F90
M      src/atmosphere/land_surface/pdm/F90

which shows no files in conflict. At this stage you would usually think about committing your change to the branch, but please don't do it for this example.


  • FCM User Guide on Resolving Conflicts
  • xxdiff manual, "Merging files and resolving conflicts"
  • xxdiff manual

For queries / corrections / suggestions email: r.s.hatcher(at)reading.ac.uk

Last modified 11 years ago Last modified on 11/18/08 14:33:48