Google Summer of Code '19: Add functionality to store an unresolved merge-state

Pierre-Yves David pierre-yves.david at
Tue May 14 08:21:17 EDT 2019

On 5/12/19 8:31 PM, Navaneeth Suresh wrote:
> Hello everyone,
> I am Navaneeth Suresh, one of the GSoC '19 students with Mercurial. I 
> wanted to discuss my project on adding functionality to store an 
> unresolved merge-state[1] 
> <> with 
> the community. Having gone through past mailing list archives on similar 
> issues, I got some ideas on the implementation of the project. However, 
> there can be other alternatives and I might encounter some issues which 
> I might not aware of. So, I'm sharing my idea of implementation.
> As said by @marmoute, we are storing only one active unresolved 
> merge-state.

Yes, the active merge state exists in .hg/merge/. It is used for the 
operation the triggered a merge (hg merge, hg rebase, etc) and will 
exist until the merge is concluded or aborted.

As far as I understand your project, is to offer a third alternative: 
delaying the merge resolution until later. Right ?

How do you see the final user experience? What is the workflow to delay 
and later conclude/abort a merge? (note: there are some UX details from 
you later in this email, but it probably worth being explained 

> I am thinking to store it as a visible commit under a 
> bookmark having the prefix `conflict/`.

That seems strange. We usually don't do this "data behind a bookmark 
namespace" in Mercurial. We have a "internal" phase dedicated to commit 
that are internal by product. That would be more appropriate.

However, I am not sure we actually need a special commit. We could store 
conflict directly into the commit they intend to be part once resolved. 
That would simplify the storage and the UX. (more on that later)

> This should contain metadata 
> about the files which are marked as resolved/unresolved by the user. I 
> have coded this and made this work by respecting both parents without 
> changing the default behavior of `localrepo.commit()` (adding metadata 
> about conflicts part is left.)

What format do you intend to use. What do you plan to do to preserve the 
file content

> This conflicted state can be later 
> restored by rebasing the tip on the top of the commit just before the 
> conflict commit and stripping the conflict commit from the DAG. The 
> restoring functionality is much hypothetical at the moment and there are 
> things to investigate on that.

Okay, the workflow is a bit clearer to me now. However it seems quite 
complicated. I would propose a slightly different approach. Let me start 
with a simple example:

You are trying to do a merge but there are conflict.

   $ hg merge
   3 files updated, 2 files merged, 0 files removed, 2 files unresolved

Some of the file can be resolved, but one of the conflict remains 
difficult and you need to delay its resolution

   $ hg resolve -l
   R foo
   U bar

My idea would be add a flag to make it possible to commit anyway. 
Something like:

   $ hg commit --unresolved

At that point we have a "regular" merge commit but with some 
"unresolved" flag. And the related data can also be stored there.

At that point, this "unresolved" commit cannot move to the public phase.

   $ hg phase --public

However it can get resolved.

   $ hg up YOURMERGE
   $ hg resolve -l
   R foo
   U bar
   $ hg resolve bar
   $ hg resolve -l
   R foo
   R bar

And the merge can be concluded (not sure of the UI)

   $ hg merge --continue

or maybe.

   $ hg amend

> If anyone of you has other thoughts on the implementation, I would love 
> to hear that. Also, pros, cons, feasibility, etc. on this proposed way 
> of implementation are also welcome.

We need a plan that works well for:

   * hg merge
   * hg rebase & co (similar to merge, but a bit different)
   * hg update
   * hg shelve

The approach of "just do a regular commit" works well for `hg merge` and 
`hg rebase`. It is a bit less clear with `hg shelve` and `hg update` and 
  need more thinking.
The idea also comes with interesting properties, for example, you can 
shelve an unresolved merge.

The main technical questions are:

A) How do we flag a changesets as "unresolved"
b) Where do we store the usual merge-state information ?
c) Where we store the multiple alternative content for the unresolved 
file (local version, current version, [remote version])

I believe all of the above can be solved with a combination of existing 
tools. changesets, extra, manifest flag, revlog metadata.

I can also see a couple of other technical questions.

* preventing unresolved changeset publishing
* propagating unresolution (what happen when you rebase a change to a 
file unresolved

And of course the general question of the user experience and comand 

If you like the plan, we can discuss it more. Can help you to clarify 
the remaining questions and design the technical bits. I suggest we 
focus on `hg merge` for now. This is the simplest case.


Pierre-Yves David

More information about the Mercurial-devel mailing list