[RFC] A better way to help users understand and resolve confclits

Guilhem Bichot guilhem at sun.com
Tue Aug 25 11:08:16 BST 2009


Hello Vincent,

Vincent Ladeuil a écrit, Le 13.08.2009 16:03:
>>>>>> "Guilhem" == Guilhem Bichot <guilhem at sun.com> writes:
> 
> <snip/>
> 
>     Guilhem> I think what can enlighten users most is explanations like you wrote:
> 
>     Guilhem> bzr resolve --interactive <item>
> 
>     Guilhem> <base> is <revid>/<revno>
>     Guilhem> <other> wants to create <item> bzr created <item>.moved
>     Guilhem> <this> keeps <item>
>     Guilhem> 1) Right, get rid of .moved
>     Guilhem> 2) Wrong, .moved is the good one, get rid of <item>
>     Guilhem> 3) Abort, let me handle that myself.
>     Guilhem> 4) Do nothing, just mark as resolve

When I started doing MySQL code merges using bzr, which are often large 
(tens of conflicted files), I quickly hit the problem that for most text 
conflicts, I couldn't take a good decision without looking at revision 
history of the TREE and MERGE-SOURCE branches. Here's an example:

<<<TREE
2
===BASE
1
===
 >>>MERGE-SOURCE

That is, TREE changed a line whereas MERGE-SOURCE deleted it.
Then what should I do:
- if MERGE-SOURCE just deleted "1", I may consider deleting "2"
- but if MERGE-SOURCE deleted "1" and inserted it in some other file 
(that is, it was actually a code move), I should rather delete "2" and 
put it into some other file.
So I need to see the diff associated with the revision which deleted "1" 
(to see if "1" was put in some other file). Either through "bzr 
gannotate" or "bzr qlog FILE", usually.

This is even more pressing when using --weave where there is no BASE 
section.

Fortunately there is a GUI plugin which I now use for every merge:
https://launchpad.net/tetard
As useful goodies, it also allows doing graphical diffs between the TREE 
and merged file (so that, after doing lots of editing to fix several 
conflicts in one file, you can see what you have done).

Given that "bzr resolve --interactive" and this plugin have similar 
goals (except that one is a GUI), and I know the plugin has made my 
merge experience easier, I suggest looking at features of the plugin as 
one source of inspiration.

Here's the help text for the GUI plugin:

***********
Purpose: A graphical user interface to help conflict resolution in merges
Usage:   bzr mergeboard

Options:
   -v, --verbose         Display more information.
   -q, --quiet           Only display errors and warnings.
   -e ARG, --editor=ARG  editor program (default: from EDITOR environment
                         variable)
   --usage               Show usage message and options.
   -d ARG, --diff=ARG    diff program (default: kdiff3)
   -h, --help            Show help message.

Description:
   Assuming you are merging branch B into branch A: to use this command,
   you need three checked-out branches on disk:
   - "local branch": A
   - "remote branch": B
   - "merge branch": a branch identical to A, where you have started the 
merge:
      bzr branch A A_merge; cd A_merge; bzr merge B; bzr mergeboard
   Fill in the "local" and "remote" text entries, pick a conflicted file
   in the drop-down list, then use buttons.
   This command is limited to text conflicts.
   The "revtool" buttons assumes that you have a plugin providing a
   "bzr revtool FILENAME" command.
   The "extmerge" button assumes that you have the "extmerge" plugin.
   The "gannotate" buttons assumes that you have the "bzr-gtk" plugin.
   To create a shortcut for this command, see "bzr help alias"
**********

At least, if it's impossible to display revision history via 'bzr 
resolve --interactive', a greatly flexible workaround could be to allow 
the user to define, via some configuration variables, additional actions 
for this command; it could look like this in the '.conf' file:

resolve_interactive=("Text", "annotate TREE version", "bzr gannotate 
%t"),("Text", "display history of MERGE-SOURCE version", "bzr qlog %m")

where:
- "Text" means that the action should be added only when the conflict is 
of type "Text"
- the second element of the sequence is the human-readable description 
of the action
- the third element is a system command which would be executed; %t 
stands for "a path to the TREE version of the file" and %m for "a path 
to the MERGE-SOURCE version of the file" (possibly magically put in a 
temporary file before executing the action).

And then 'bzr resolve --interactive' would look like:
1) built-in action (do this)
2) built-in other action (do that)
3) abort, let me handle it
4) just mark it resolved
5) annotate TREE version
6) display history of MERGE-SOURCE version

Note that the tetard plugin executes "gannotate" in a non-blocking mode 
(GUI returns control before the "bzr gannotate" window is closed), so 
that you can have several annotate or history windows open at the same 
time, which helps in certain cases (history of TREE and history of 
MERGE-SOURCE for example).

-- 
Mr. Guilhem Bichot <guilhem at sun.com>
Sun Microsystems / MySQL, Lead Software Engineer
Bordeaux, France
www.sun.com / www.mysql.com



More information about the bazaar mailing list