[RFC] A better way to help users understand and resolve confclits
Martin Pool
mbp at canonical.com
Thu Aug 13 11:24:53 BST 2009
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: v.ladeuil+lp at free.fr-20090813062135-mvkhie71vei48lco
# target_branch: http://bazaar.launchpad.net/~bzr/bzr/trunk
# testament_sha1: 3be971b687974080fdef496223ca9e881315931e
# timestamp: 2009-08-13 10:38:51 +0200
# base_revision_id: pqm at pqm.ubuntu.com-20090811040617-g99p5v2wsn13ww8z
#
# Begin patch
=== added file 'Outline.txt'
--- Outline.txt 1970-01-01 00:00:00 +0000
+++ Outline.txt 2009-08-13 06:21:35 +0000
I guess you atually want to put this into doc/developers/conflict-handling or
something?
@@ -0,0 +1,186 @@
+When conflicts are present in a working tree (as shown by ``bzr
+conflicts``), the user should resolve them and then inform bzr
+that the conflicts has been resolved.
+
+Resolving conflicts is sometimes not obvious. Either because the
+user that should resolve them is not the one responsible for
+their occurrence, as it's the case when merging other people work
s//as is the case/
+or because some conflicts are presented in a way that is not easy
+to understand.
+
+``bzr`` try to avoid conflicts.
+
+When it can't, it add information into the working tree to
+present the conflicting versions and leave the resolution to the
+user.
What we aim for here is that we will ask the user to resolve the conflict if
and only if there's an actual conceptual conflict in the source tree. Because
the tool doesn't understand the real meaning of the files being versioned we
can fall short in either direction.
+
+Whatever the conflict is, resolving it is roughly done in two steps:
+
+- modify the working tree content so that the conflicted item is
+ now in the desired state, there are,
+
+- inform bzr that the conflict is now solved and ask to cleanup
+ any remaining generated information (``bzr resolve <item>``).
That's true at the moment. I'm not sure if it should always be true.
Also, I have some doubts about whether we should really have a separate
'resolve' step that means only "I resolved it".
If the user edited the file to remove all the conflict markers, we can tell
this mechanically and it's fairly obvious that they now consider the file to be
ok. Obviously you would have to accomodate the case where the user actually
wants to commit a file that apparently (or really) contains conflict
markers, but that
shouldn't cause extra work in the other 99% of cases.
I do think it's useful that the resolution can be done in multiple steps,
possibly restarting bzr or rebooting the machine in between - it's not enough,
as bk does/did to do it all synchronously in the merge process. However, I
would really question whether getting people to use bzr mv/rm manually to
resolve conflicts is a good ui. It doesn't give enough information about what
question they're answering.
We'd want to also keep a non-interactive command line interface to do these
changes for the use of things like emacs.
+
+
+For most conflict types, there are some obvious ways to modify
+the working tree and put it into the desired state. For some type
+of conflicts, bzr itself already made a choice when possible.
+
+Yet, whether bzr made a choice or not, there are some other ways
+simple but alternative ways to resolve the conflict.
+
+Providing the ``--interactive`` option to ``bzr resolve`` will
+display a short explanation of the conflict and propose some
+actions before marking the file as resolved.
Arguably merge should optionally take you straight into this.
It seems like following this point you're making a list of the different types
of conflicts.
+Text conflicts:
+---------------
+
+3 ways:
+- force THIS
+- force OTHER
+- manually solve each conflicted region
+
+resolve:
+- delete .THIS, .OTHER, .BASE if present
+
+Content conflicts:
+------------------
How is this different? Content conflicts for directories or symlinks?
Another kind of conflict (which may fit into one of your categories) is
deletion of a directory containing unversioned files.
If you search the bug tracker you may find some further interesting cases.
+
+3 ways:
+- bzr mv .THIS <item>,
+- bzr mv .OTHER <item>,
+- manually combine .THIS and .OTHER
+
+resolve:
+- delete .THIS, .OTHER, .BASE if present
+
+
+Duplicate paths
+---------------
+
+bzr made a choice
+
+3 ways:
+- bzr mv .moved <item> (refuse bzr choice)
+- bzr rm .moved (accept bzr choice)
+- manually combine <item> and .moved
+
+resolve:
+- delete .moved if still present ? (not done so far ?)
+
+
+Unversioned parent
+------------------
+
+bzr made a choice: version the parent
+
+3 ways:
+- bzr rm <children>
+- bzr rm <parent>
+- manually rename <children>
+
+resolve:
+- nothing to do ?
+
+XXX: need investigation to enumerate all cases
+
+
+Missing parent
+--------------
+
+bzr made a choice: create the missing parent and version it.
+
+3 ways:
+- bzr rm <children>
+- bzr rm <parent>
+- manually rename <children>
+
+resolve:
+- nothing to do ?
+
+XXX: need investigation to enumerate all cases
+
+
+Deleting parent
+---------------
+
+bzr made a choice: not delete the parent
+
+3 ways:
+- bzr rm <children>
+- bzr rm <parent>
+- manually solve the issue (may be more than a single children)
+
+resolve:
+- nothing to do
+
+
+Path conflict
+-------------
+
+bzr made a choice: use the source's name
+
+3 ways:
+- do nothing (accept bzr choice)
+- bzr mv <item> other-name (refuse bzr choice)
+- manually rename to a different name
+
+resolve:
+- nothing to do
+
+Parent loop
+-----------
+
+bzr made a choice: keep the existing renaming
+
+3 ways:
+- do nothing (accept bzr choice)
+- bzr mv this_parent/this_children other_parent/other_children
+- manually rename the items
+
+resolve:
+- nothing to do
+
+
+Non-directory parent
+--------------------
+
+bzr made a choice: create a <parent>.new directory
+
+There is no obvious single action that can solve the conflict
+here, but let's try anyway.
+
+3 ways:
+- bzr rm <parent>.new
+- bzr rm <parent> + bzr mv <parent>.new <parent>
+- manually rename the items
+
+resolve:
+- nothing to do
+
+Design:
+=======
+
+The Conflict classes will receive additional methods to resolve
+the conflict in alternative ways.
+
+Resolve will receive a ``--interactive`` option and present a
+list of possible actions (including do nothing) to the user
+before marking the file as resolved.
+
+It should be possible for a GUI to query the conflict objects for
+possible actions (in textual form) and trigger them.
+
+TODO:
+
+- add more info to Conflict objects:
+ -
+ - base revid for text conflict
+
+- tests with '.diverted' files ?
+
+- doc/es/user-guide/resolving_conflicts.txt is really
+ use-reference/resolving_conflicts.txt
+
=== modified file 'bzrlib/conflicts.py'
--- bzrlib/conflicts.py 2009-03-23 14:59:43 +0000
+++ bzrlib/conflicts.py 2009-08-13 06:19:32 +0000
@@ -480,7 +480,7 @@
class UnversionedParent(HandledConflict):
- """An attempt to version an file whose parent directory is not versioned.
+ """An attempt to version a file whose parent directory is not versioned.
Typically, the result of a merge where one tree unversioned the directory
and the other added a versioned file to it.
"""
=== modified file 'bzrlib/help_topics/en/conflicts.txt'
--- bzrlib/help_topics/en/conflicts.txt 2007-12-25 04:17:50 +0000
+++ bzrlib/help_topics/en/conflicts.txt 2009-08-13 06:19:32 +0000
@@ -181,7 +181,7 @@
Conflict: FILE.new is not a directory, but has files in it.
Created directory.
-This happens when one side has added files to a directory, and the othe side
+This happens when one side has added files to a directory, and the other side
has changed the directory into a file or symlink. For example::
$ bzr init
More information about the bazaar
mailing list