Patchwork [evolve-ext] fold: add argument to handle ambiguous case

login
register
mail settings
Submitter Laurent Charignon
Date May 28, 2015, 9:01 p.m.
Message ID <0821817a847922104981.1432846917@lcharignon-mbp.local>
Download mbox | patch
Permalink /patch/9347/
State Changes Requested
Headers show

Comments

Laurent Charignon - May 28, 2015, 9:01 p.m.
# HG changeset patch
# User Laurent Charignon <lcharignon@fb.com>
# Date 1432845532 25200
#      Thu May 28 13:38:52 2015 -0700
# Node ID 0821817a84792210498107777181dcc9f1d68ec7
# Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
fold: add argument to handle ambiguous case

Before this patch, when a user was using fold for the first times he could
think that --exact is the default behavior and make a mistake.
For example hg fold -r 12+13 won't just fold revision 12 and 13 together but
12, 13 and the linear chain of revision upto the working directory's parent.

This patch introduces a new option when the selection is ambiguous: when the
user specified two or more revisions not including the working copy's parent
without using --exact flag.
When the user is giving only one revision we assume that the intent of the user
is clearly to fold the chain from that revision up to the working directory's
parent. Example of change assuming that we have a linear history from rev 1 to
10 and the working copy parent is 10:

hg fold 9 # will fold 9 and 10 together, unchanged

hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error

hg fold 8 + 7 --chain # folds 7,8,9,10 together

hg fold 8 + 7 --exact # folds 7 and 8 together

hg fold 7:: # fold 7,8,9,10 it is not ambiguous as 10 is in the set

hg fold 7::9 # now prints an error and does not fold 7,8,9,10 anymore
Jordi Gutiérrez Hermoso - May 28, 2015, 10:25 p.m.
On Thu, 2015-05-28 at 14:01 -0700, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon@fb.com>
> # Date 1432845532 25200
> #      Thu May 28 13:38:52 2015 -0700
> # Node ID 0821817a84792210498107777181dcc9f1d68ec7
> # Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
> fold: add argument to handle ambiguous case
> 
> Before this patch, when a user was using fold for the first times he could
> think that --exact is the default behavior and make a mistake.
> For example hg fold -r 12+13 won't just fold revision 12 and 13 together but
> 12, 13 and the linear chain of revision upto the working directory's
> parent.

Yes, this is quite intentionally the fold behaviour. Pierre-Yves and I
hashed it out a while ago.

> This patch introduces a new option when the selection is ambiguous:
> when the user specified two or more revisions not including the
> working copy's parent without using --exact flag.

Your definition of ambiguous doesn't match what Pierre-Yves and I had
in mind when we discussed this behaviour before. For example, `hg fold
-r 'draft() and tag()'` is a completely reasonable thing to do, may
select more than one commit, and it should fold with the current
commit. There are other revsets that could operate similarly and
should not be considered "ambiguous".

I really think the current fold behaviour should stay. An error with
fold is easy to undo using `hg touch` and `hg prune --succ`. There is
a way out, and we should nudge users towards not using `hg fold
--exact` by default. I worked on making the fold docstring short
enough to be clear and not tl;dr.
Matt Mackall - May 28, 2015, 10:26 p.m.
On Thu, 2015-05-28 at 14:01 -0700, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon@fb.com>
> # Date 1432845532 25200
> #      Thu May 28 13:38:52 2015 -0700
> # Node ID 0821817a84792210498107777181dcc9f1d68ec7
> # Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
> fold: add argument to handle ambiguous case
> 
> Before this patch, when a user was using fold for the first times he could
> think that --exact is the default behavior and make a mistake.
> For example hg fold -r 12+13 won't just fold revision 12 and 13 together but
> 12, 13 and the linear chain of revision upto the working directory's parent.
> 
> This patch introduces a new option when the selection is ambiguous: when the
> user specified two or more revisions not including the working copy's parent
> without using --exact flag.
> When the user is giving only one revision we assume that the intent of the user
> is clearly to fold the chain from that revision up to the working directory's
> parent. Example of change assuming that we have a linear history from rev 1 to
> 10 and the working copy parent is 10:
> 
> hg fold 9 # will fold 9 and 10 together, unchanged

Ok. 

> hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error

What is the user story where this is what's wanted? If the answer is
"never" (which I suspect), then we should just make this do what's
expected: fold the specified versions with each other.

> hg fold 8 + 7 --chain # folds 7,8,9,10 together

Why would anybody type that rather than:

 hg fold --chain 7

Adding + 8 doesn't add any additional info except maybe "I'm trying to
do something different and am about to have a sad."

It seems to me that both --exact and --chain are unnecessarily
complicated. We should really consider an interface that's simply:

 hg fold start::end

with no magic defaults.
Jordi Gutiérrez Hermoso - May 28, 2015, 10:56 p.m.
On Thu, 2015-05-28 at 14:01 -0700, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon@fb.com>
> # Date 1432845532 25200
> #      Thu May 28 13:38:52 2015 -0700
> # Node ID 0821817a84792210498107777181dcc9f1d68ec7
> # Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
> fold: add argument to handle ambiguous case
[snip]
> +            ui.write_err(_('multiple revisions specified not including the'
> +            ' parent of the working.\n'
> +            'Please use one of:\n'
> +            '   --exact to fold exactly these revisions\n'
> +            '   --chain to fold the chain from these revisions upto the parent'
> +            'of the working copy\n'))
> +            return 1

Too verbose. Mercurial error messages must fit in a single line, plus
an optional hint, which must also fit in a single line. Like the Bard
wrote, "brevity is the soul of wit."

If we really are going to error out in this case, which I still
oppose, this error should raise util.Abort with a one-line error
message and perhaps a one-line hint. If you cannot fit a clear
explanation in that space, the average user will not read it and/or
will not understand it.
Laurent Charignon - May 28, 2015, 11:13 p.m.
On 5/28/15, 3:26 PM, "Matt Mackall" <mpm@selenic.com> wrote:

>On Thu, 2015-05-28 at 14:01 -0700, Laurent Charignon wrote:
>> # HG changeset patch
>> # User Laurent Charignon <lcharignon@fb.com>
>> # Date 1432845532 25200
>> #      Thu May 28 13:38:52 2015 -0700
>> # Node ID 0821817a84792210498107777181dcc9f1d68ec7
>> # Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
>> fold: add argument to handle ambiguous case
>> 
>> Before this patch, when a user was using fold for the first times he
>>could
>> think that --exact is the default behavior and make a mistake.
>> For example hg fold -r 12+13 won't just fold revision 12 and 13
>>together but
>> 12, 13 and the linear chain of revision upto the working directory's
>>parent.
>> 
>> This patch introduces a new option when the selection is ambiguous:
>>when the
>> user specified two or more revisions not including the working copy's
>>parent
>> without using --exact flag.
>> When the user is giving only one revision we assume that the intent of
>>the user
>> is clearly to fold the chain from that revision up to the working
>>directory's
>> parent. Example of change assuming that we have a linear history from
>>rev 1 to
>> 10 and the working copy parent is 10:
>> 
>> hg fold 9 # will fold 9 and 10 together, unchanged
>
>Ok. 
>
>> hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error
>
>What is the user story where this is what's wanted? If the answer is
>"never" (which I suspect), then we should just make this do what's
>expected: fold the specified versions with each other.
>
>> hg fold 8 + 7 --chain # folds 7,8,9,10 together
>
>Why would anybody type that rather than:
>
> hg fold --chain 7
>
>Adding + 8 doesn't add any additional info except maybe "I'm trying to
>do something different and am about to have a sad."
>
>It seems to me that both --exact and --chain are unnecessarily
>complicated. We should really consider an interface that's simply:
>
> hg fold start::end
>
>with no magic defaults.

Sure, that was the default before and I agree with you on that, it seems
logical to me.

But apparently there has already been a discussion on the default behavior:
- Before, the default behavior was what --exact does today and 'hg fold
start::end' was folding from start to end as your describe
- Pierre-Yves and others realized that they were often using 'hg fold
start::' to fold everything linearly from start to the parent of the
working copy.
- The decision was made to make the default to fold the chain of revisions
from the one specified to the parent of the working copy, so hg fold
start::end fold from start to end and end to the parent of the working copy

Pierre-Yves, is that correct?


>
>-- 
>Mathematics is the supreme nostalgia of our time.
>
Laurent Charignon - May 28, 2015, 11:13 p.m.
On 5/28/15, 3:25 PM, "Jordi Gutiérrez Hermoso" <jordigh@octave.org> wrote:

>On Thu, 2015-05-28 at 14:01 -0700, Laurent Charignon wrote:
>> # HG changeset patch
>> # User Laurent Charignon <lcharignon@fb.com>
>> # Date 1432845532 25200
>> #      Thu May 28 13:38:52 2015 -0700
>> # Node ID 0821817a84792210498107777181dcc9f1d68ec7
>> # Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
>> fold: add argument to handle ambiguous case
>> 
>> Before this patch, when a user was using fold for the first times he
>>could
>> think that --exact is the default behavior and make a mistake.
>> For example hg fold -r 12+13 won't just fold revision 12 and 13
>>together but
>> 12, 13 and the linear chain of revision upto the working directory's
>> parent.
>
>Yes, this is quite intentionally the fold behaviour. Pierre-Yves and I
>hashed it out a while ago.
>
>> This patch introduces a new option when the selection is ambiguous:
>> when the user specified two or more revisions not including the
>> working copy's parent without using --exact flag.
>
>Your definition of ambiguous doesn't match what Pierre-Yves and I had
>in mind when we discussed this behaviour before. For example, `hg fold
>-r 'draft() and tag()'` is a completely reasonable thing to do, may
>select more than one commit, and it should fold with the current
>commit. There are other revsets that could operate similarly and
>should not be considered "ambiguous".

Sure and it will because the working copy is in draft(), right?

>
>I really think the current fold behaviour should stay. An error with
>fold is easy to undo using `hg touch` and `hg prune --succ`. There is
>a way out, and we should nudge users towards not using `hg fold
>--exact` by default. I worked on making the fold docstring short
>enough to be clear and not tl;dr.
>
>
Pierre-Yves David - May 29, 2015, 1:22 a.m.
On 05/28/2015 03:25 PM, Jordi Gutiérrez Hermoso wrote:
> On Thu, 2015-05-28 at 14:01 -0700, Laurent Charignon wrote:
>> # HG changeset patch
>> # User Laurent Charignon <lcharignon@fb.com>
>> # Date 1432845532 25200
>> #      Thu May 28 13:38:52 2015 -0700
>> # Node ID 0821817a84792210498107777181dcc9f1d68ec7
>> # Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
>> fold: add argument to handle ambiguous case
>>
>> Before this patch, when a user was using fold for the first times he could
>> think that --exact is the default behavior and make a mistake.
>> For example hg fold -r 12+13 won't just fold revision 12 and 13 together but
>> 12, 13 and the linear chain of revision upto the working directory's
>> parent.
>
> Yes, this is quite intentionally the fold behaviour. Pierre-Yves and I
> hashed it out a while ago.

Laurent pointed to me that he foot-gunned himself with the current 
behvior expecting '--exact' to be the current behavior. I explained him 
(for context) how we came to the current behavior (majority of observed 
use case are: `hg fold `(.~X)::.`). But I'm unhappy of seeing user 
shooting themself in the foot. So if he is giving a shot at trying 
something more safe.

>> This patch introduces a new option when the selection is ambiguous:
>> when the user specified two or more revisions not including the
>> working copy's parent without using --exact flag.
>
> Your definition of ambiguous doesn't match what Pierre-Yves and I had
> in mind when we discussed this behaviour before. For example, `hg fold
> -r 'draft() and tag()'` is a completely reasonable thing to do, may
> select more than one commit, and it should fold with the current
> commit. There are other revsets that could operate similarly and
> should not be considered "ambiguous".

I think Laurent approach here is "if there is multiple revs, this is 
suspicious and I ask for details". I'm not sure if I'm sold yet, but 
this is much better than "have different behavior accorting revset result"

> I really think the current fold behaviour should stay. An error with
> fold is easy to undo using `hg touch` and `hg prune --succ`. There is
> a way out, and we should nudge users towards not using `hg fold
> --exact` by default. I worked on making the fold docstring short
> enough to be clear and not tl;dr.

We definitly aims at having an easy way to restore things to a previous 
state. But the current User experience for it is atrocious so we have to 
take some of that in account not. However this should not dictate the 
final shape of the UI (yes, some contradiction here, my point is "do not 
pretend restoring is 'simple'").
Pierre-Yves David - May 30, 2015, 1:29 a.m.
On 05/28/2015 03:26 PM, Matt Mackall wrote:

[reordered]

 > It seems to me that both --exact and --chain are unnecessarily
 > complicated. We should really consider an interface that's simply:
 >
 >   hg fold start::end
 >
 > with no magic defaults.

Lets write some history here...

In the dawn of time, the behavior was:
   hg fold <revset>
  -> fold everything in <revset> together.
   (This match the `hg fold start::end` from Matt.)

There was two issue with this UI:

1) It pretty much requires the knowledge of revset to be used 
efficiently. This put the barrier of entry higher than necessary for a 
fairly basic command.

2) The most common case turned out to be, I want to fold the last N 
commits. This happen commonly when one is working toward something, 
making frequent wip commit along the way to be able to easily go back to 
a check point. So the common case was `hg fold X::.`

(This two principle seems important to: (1) do not requires revset 
knowledge to ensure a low barrier of entry (2) default case should be easy).


So, we move the default to :

   hg fold <rev>
  -> fold everything between '.' and <rev>.

   hg fold --exact <revset>
   -> fold everything in the revset.

I think that putting the advanced use case of 'folding anywhere' is an 
okay choice.

Most of mercurial command behave according the working directory parent

- commit -> make a commit as child as '.'
- amend -> add content to '.'
- uncommit -> remove content to '.'
- hg split -> split '.' into multiple changeset (in the future)
- diff -> show difference with '.'
- revert -> restore file as in '.'
- merge -> merge '.' with something else
- rebase -> rebase '.' somewhere else (by default)
- graft -> get a new commit on top of '.'
- histedit -> histedit from '.' to X
   (would be nice to have an '--exact' here actually)
- hg evolve -> evolve stuff related to '.'

So I think it at most sensible (and at best consistent) with the other 
commands than the default involves the working copy.

[former message start]

>> hg fold 9 # will fold 9 and 10 together, unchanged
>
> Ok.
>
>> hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error
>
> What is the user story where this is what's wanted? If the answer is
> "never" (which I suspect), then we should just make this do what's
> expected: fold the specified versions with each other.

I believe "8+7" is only used here as an example. It is a place holder 
for 'anycomplicatedrevset()'. In that case, the revset result could be 
said "visually obvious" but the internal code have no clue about.

My personal philosophy is:

   "We should lever change behavior accord length of a revset result"

When I run a command with '::myfeature - public()' I dunno if this is 
going to return 0, 1, 2 or N changeset. But I still want to be able to 
build alias for it and run command without double checking revset lengh. 
Therefore, command cannot change there behavior regarding revset query 
result because that will blow in my face all the time.

>> hg fold 8 + 7 --chain # folds 7,8,9,10 together
>
> Why would anybody type that rather than:
>
>   hg fold --chain 7

CF, previous comment. Nobody is going to type 7+8. But revset result 
will be 7+8

> Adding + 8 doesn't add any additional info except maybe "I'm trying to
> do something different and am about to have a sad."
Pierre-Yves David - May 30, 2015, 1:36 a.m.
On 05/28/2015 02:01 PM, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon@fb.com>
> # Date 1432845532 25200
> #      Thu May 28 13:38:52 2015 -0700
> # Node ID 0821817a84792210498107777181dcc9f1d68ec7
> # Parent  69e5de3e6129185469c2cbf98383ac6d58260d0c
> fold: add argument to handle ambiguous case
>
> Before this patch, when a user was using fold for the first times he could
> think that --exact is the default behavior and make a mistake.
> For example hg fold -r 12+13 won't just fold revision 12 and 13 together but
> 12, 13 and the linear chain of revision upto the working directory's parent.
>
> This patch introduces a new option when the selection is ambiguous: when the
> user specified two or more revisions not including the working copy's parent
> without using --exact flag.
> When the user is giving only one revision we assume that the intent of the user
> is clearly to fold the chain from that revision up to the working directory's
> parent. Example of change assuming that we have a linear history from rev 1 to
> 10 and the working copy parent is 10:

After more though, I may be less sold to this than originally, The 
warning is still a bit random (depends of revset result). Let me think 
about it while the full design discussion about the UI unroll and we'll 
see what we finally wants to do. The good point is that the most basic 
case `hg fold 3475341` and `hg fold .~5` won't trigger the warning so 
this is probably okay.

Also: I'm not fan of '--chain' maybe we can explore '--with' or 
'--up-to' or something similar?

Small nit: The core of your patch is 'adding --chain argument', it 
'--chain' should appear in the first line or first paragraph.

>
> hg fold 9 # will fold 9 and 10 together, unchanged
>
> hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error
>
> hg fold 8 + 7 --chain # folds 7,8,9,10 together
>
> hg fold 8 + 7 --exact # folds 7 and 8 together
>
> hg fold 7:: # fold 7,8,9,10 it is not ambiguous as 10 is in the set
>
> hg fold 7::9 # now prints an error and does not fold 7,8,9,10 anymore
>
> diff --git a/hgext/evolve.py b/hgext/evolve.py
> --- a/hgext/evolve.py
> +++ b/hgext/evolve.py
> @@ -2263,7 +2263,9 @@
>
>   @command('^fold|squash',
>       [('r', 'rev', [], _("revision to fold")),
> -     ('', 'exact', None, _("only fold specified revisions"))
> +     ('', 'exact', None, _("only fold specified revisions")),
> +     ('', 'chain', None, _('fold the chain of revisions between the given '
> +                           'revisions and the parent of the working copy')),
>       ] + commitopts + commitopts2,
>       _('hg fold [OPTION]... [-r] REV'))
>   def fold(ui, repo, *revs, **opts):
> @@ -2308,6 +2310,14 @@
>       revs = scmutil.revrange(repo, revs)
>
>       if not opts['exact']:
> +        if len(revs) > 1 and not opts['chain'] and not repo['.'].rev() in revs:
> +            ui.write_err(_('multiple revisions specified not including the'
> +            ' parent of the working.\n'
> +            'Please use one of:\n'
> +            '   --exact to fold exactly these revisions\n'
> +            '   --chain to fold the chain from these revisions upto the parent'
> +            'of the working copy\n'))
> +            return 1

as pointed by Jordi, this should be an abort error fitting on one line. 
With possibly a hint.

>           # Try to extend given revision starting from the working directory
>           extrevs = repo.revs('(%ld::.) or (.::%ld)', revs, revs)
>           discardedrevs = [r for r in revs if r not in extrevs]
> diff --git a/tests/test-evolve.t b/tests/test-evolve.t
> --- a/tests/test-evolve.t
> +++ b/tests/test-evolve.t
> @@ -634,7 +634,14 @@
>     $ hg fold -r 4 -r 6 --exact
>     abort: cannot fold non-linear revisions (multiple roots given)
>     [255]
> -  $ hg fold 10 1
> +Two revisions in the middle of the stack, ambiguous behavior
> +  $ hg fold -r '4+5'
> +  multiple revisions specified not including the parent of the working.
> +  Please use one of:
> +     --exact to fold exactly these revisions
> +     --chain to fold the chain from these revisions upto the parentof the working copy
> +  [1]
> +  $ hg fold 10 1 --chain
>     abort: cannot fold non-linear revisions
>     (given revisions are unrelated to parent of working directory)
>     [255]
> @@ -642,14 +649,19 @@
>     $ hg fold -r 0
>     abort: cannot fold public revisions
>     [255]
> +
> +Two revisions including the parent of the working copy
> +  $ hg fold -r '6 + 10'
> +  2 changesets folded
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>     $ hg fold -r 5
> -  3 changesets folded
> -  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  2 changesets folded
> +  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
>     $ hg fold 6 # want to run hg fold 6
>     abort: hidden revision '6'!
>     (use --hidden to access hidden revisions)
>     [255]
> -  $ hg log -r 11 --template '{desc}\n'
> +  $ hg log -r 12 --template '{desc}\n'
>     add 3
>
>
> @@ -664,21 +676,21 @@
>
>     $ hg up 4
>     0 files updated, 0 files merged, 2 files removed, 0 files unresolved
> -  $ hg fold --rev 4::11 --user victor --exact
> +  $ hg fold --rev 4::12 --user victor --exact
>     2 changesets folded
>     2 files updated, 0 files merged, 0 files removed, 0 files unresolved
>     $ glog
> -  @  12:d26d339c513f@default(draft) add 4
> +  @  13:d26d339c513f@default(draft) add 4
>     |
>     | o  1:73d38bb17fd7@default(draft) add 1
>     |/
>     o  0:8685c6d34325@default(public) add 0
>
>     $ hg log --template '{rev}: {author}\n'
> -  12: victor
> +  13: victor
>     1: test
>     0: test
> -  $ hg log -r 12 --template '{desc}\n'
> +  $ hg log -r 13 --template '{desc}\n'
>     add 4
>
>
> @@ -696,32 +708,32 @@
>
>     $ hg olog
>     4	: add 4 - test
> -  11	: add 3 - test
> +  12	: add 3 - test
>
>   Test obsstore stat
>
>     $ hg debugobsstorestat
> -  markers total:                     10
> -      for known precursors:          10
> +  markers total:                     11
> +      for known precursors:          11
>         with parents data:              0
>     markers with no successors:         0
> -                1 successors:        10
> +                1 successors:        11
>                   2 successors:         0
>         more than 2 successors:         0
>         available  keys:
> -                 user:               10
> +                 user:               11
>     disconnected clusters:              1
>             any known node:             1
> -          smallest length:           10
> -          longer length:             10
> -          median length:             10
> -          mean length:               10
> +          smallest length:           11
> +          longer length:             11
> +          median length:             11
> +          mean length:               11
>         using parents data:             1
>             any known node:             1
> -          smallest length:           10
> -          longer length:             10
> -          median length:             10
> -          mean length:               10
> +          smallest length:           11
> +          longer length:             11
> +          median length:             11
> +          mean length:               11
>
>
>   Test evolving renames
> @@ -741,8 +753,8 @@
>     1 changesets pruned
>     1 new unstable changesets
>     $ hg stab --any
> -  move:[15] c
> -  atop:[13] a
> +  move:[16] c
> +  atop:[14] a
>     working directory is now at 3742bde73477
>     $ hg st -C --change=tip
>     A c
> diff --git a/tests/test-tutorial.t b/tests/test-tutorial.t
> --- a/tests/test-tutorial.t
> +++ b/tests/test-tutorial.t
> @@ -494,6 +494,8 @@
>
>      -r --rev VALUE [+] revision to fold
>         --exact         only fold specified revisions
> +      --chain         fold the chain of revisions between the given revisions
> +                      and the parent of the working copy

help too long.
Gilles Moris - May 30, 2015, 9:28 a.m.
Le 30/05/2015 03:29, Pierre-Yves David a écrit :
>
>
> On 05/28/2015 03:26 PM, Matt Mackall wrote:
>
> [reordered]
>
> > It seems to me that both --exact and --chain are unnecessarily
> > complicated. We should really consider an interface that's simply:
> >
> >   hg fold start::end
> >
> > with no magic defaults.
>
> Lets write some history here...
>
> In the dawn of time, the behavior was:
>   hg fold <revset>
>  -> fold everything in <revset> together.
>   (This match the `hg fold start::end` from Matt.)
>
> There was two issue with this UI:
>
> 1) It pretty much requires the knowledge of revset to be used 
> efficiently. This put the barrier of entry higher than necessary for a 
> fairly basic command.
>
> 2) The most common case turned out to be, I want to fold the last N 
> commits. This happen commonly when one is working toward something, 
> making frequent wip commit along the way to be able to easily go back 
> to a check point. So the common case was `hg fold X::.`
>
> (This two principle seems important to: (1) do not requires revset 
> knowledge to ensure a low barrier of entry (2) default case should be 
> easy).
>
>
> So, we move the default to :
>
>   hg fold <rev>
>  -> fold everything between '.' and <rev>.
>
>   hg fold --exact <revset>
>   -> fold everything in the revset.
>
> I think that putting the advanced use case of 'folding anywhere' is an 
> okay choice.
>
> Most of mercurial command behave according the working directory parent
>
> - commit -> make a commit as child as '.'
> - amend -> add content to '.'
> - uncommit -> remove content to '.'
> - hg split -> split '.' into multiple changeset (in the future)
> - diff -> show difference with '.'
> - revert -> restore file as in '.'
> - merge -> merge '.' with something else
> - rebase -> rebase '.' somewhere else (by default)
> - graft -> get a new commit on top of '.'
> - histedit -> histedit from '.' to X
>   (would be nice to have an '--exact' here actually)
> - hg evolve -> evolve stuff related to '.'
>
> So I think it at most sensible (and at best consistent) with the other 
> commands than the default involves the working copy.
>
> [former message start]
>
>>> hg fold 9 # will fold 9 and 10 together, unchanged
>>
>> Ok.
>>
>>> hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error
>>
>> What is the user story where this is what's wanted? If the answer is
>> "never" (which I suspect), then we should just make this do what's
>> expected: fold the specified versions with each other.
>
> I believe "8+7" is only used here as an example. It is a place holder 
> for 'anycomplicatedrevset()'. In that case, the revset result could be 
> said "visually obvious" but the internal code have no clue about.
>
> My personal philosophy is:
>
>   "We should lever change behavior accord length of a revset result"
>
> When I run a command with '::myfeature - public()' I dunno if this is 
> going to return 0, 1, 2 or N changeset. But I still want to be able to 
> build alias for it and run command without double checking revset 
> lengh. Therefore, command cannot change there behavior regarding 
> revset query result because that will blow in my face all the time.
>
>>> hg fold 8 + 7 --chain # folds 7,8,9,10 together
>>
>> Why would anybody type that rather than:
>>
>>   hg fold --chain 7
>
> CF, previous comment. Nobody is going to type 7+8. But revset result 
> will be 7+8
>
>> Adding + 8 doesn't add any additional info except maybe "I'm trying to
>> do something different and am about to have a sad."
>

I am not convinced that it needs 2 flags, or even 1.

Forgetting about the current UI, we could expect that providing a single 
commit would fold up to the working dir. If a complex revset is 
provided, I guess the power user could do "first(revset)". If we really 
want a flag for safety, we could use -f/--from: "hg fold -f 7".
Then if a revset yields multiple commits, I would expect the --exact 
behavior.

Regards.
Gilles.
Pierre-Yves David - May 31, 2015, 8:03 p.m.
On 05/30/2015 02:28 AM, Gilles Moris wrote:
> Le 30/05/2015 03:29, Pierre-Yves David a écrit :
>>
>>
>> On 05/28/2015 03:26 PM, Matt Mackall wrote:
>>
>> [reordered]
>>
>> > It seems to me that both --exact and --chain are unnecessarily
>> > complicated. We should really consider an interface that's simply:
>> >
>> >   hg fold start::end
>> >
>> > with no magic defaults.
>>
>> Lets write some history here...
>>
>> In the dawn of time, the behavior was:
>>   hg fold <revset>
>>  -> fold everything in <revset> together.
>>   (This match the `hg fold start::end` from Matt.)
>>
>> There was two issue with this UI:
>>
>> 1) It pretty much requires the knowledge of revset to be used
>> efficiently. This put the barrier of entry higher than necessary for a
>> fairly basic command.
>>
>> 2) The most common case turned out to be, I want to fold the last N
>> commits. This happen commonly when one is working toward something,
>> making frequent wip commit along the way to be able to easily go back
>> to a check point. So the common case was `hg fold X::.`
>>
>> (This two principle seems important to: (1) do not requires revset
>> knowledge to ensure a low barrier of entry (2) default case should be
>> easy).
>>
>>
>> So, we move the default to :
>>
>>   hg fold <rev>
>>  -> fold everything between '.' and <rev>.
>>
>>   hg fold --exact <revset>
>>   -> fold everything in the revset.
>>
>> I think that putting the advanced use case of 'folding anywhere' is an
>> okay choice.
>>
>> Most of mercurial command behave according the working directory parent
>>
>> - commit -> make a commit as child as '.'
>> - amend -> add content to '.'
>> - uncommit -> remove content to '.'
>> - hg split -> split '.' into multiple changeset (in the future)
>> - diff -> show difference with '.'
>> - revert -> restore file as in '.'
>> - merge -> merge '.' with something else
>> - rebase -> rebase '.' somewhere else (by default)
>> - graft -> get a new commit on top of '.'
>> - histedit -> histedit from '.' to X
>>   (would be nice to have an '--exact' here actually)
>> - hg evolve -> evolve stuff related to '.'
>>
>> So I think it at most sensible (and at best consistent) with the other
>> commands than the default involves the working copy.
>>
>> [former message start]
>>
>>>> hg fold 9 # will fold 9 and 10 together, unchanged
>>>
>>> Ok.
>>>
>>>> hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error
>>>
>>> What is the user story where this is what's wanted? If the answer is
>>> "never" (which I suspect), then we should just make this do what's
>>> expected: fold the specified versions with each other.
>>
>> I believe "8+7" is only used here as an example. It is a place holder
>> for 'anycomplicatedrevset()'. In that case, the revset result could be
>> said "visually obvious" but the internal code have no clue about.
>>
>> My personal philosophy is:
>>
>>   "We should lever change behavior accord length of a revset result"
>>
>> When I run a command with '::myfeature - public()' I dunno if this is
>> going to return 0, 1, 2 or N changeset. But I still want to be able to
>> build alias for it and run command without double checking revset
>> lengh. Therefore, command cannot change there behavior regarding
>> revset query result because that will blow in my face all the time.
>>
>>>> hg fold 8 + 7 --chain # folds 7,8,9,10 together
>>>
>>> Why would anybody type that rather than:
>>>
>>>   hg fold --chain 7
>>
>> CF, previous comment. Nobody is going to type 7+8. But revset result
>> will be 7+8
>>
>>> Adding + 8 doesn't add any additional info except maybe "I'm trying to
>>> do something different and am about to have a sad."
>>
>
> I am not convinced that it needs 2 flags, or even 1.
>
> Forgetting about the current UI, we could expect that providing a single
> commit would fold up to the working dir. If a complex revset is
> provided, I guess the power user could do "first(revset)". If we really
> want a flag for safety, we could use -f/--from: "hg fold -f 7".
> Then if a revset yields multiple commits, I would expect the --exact
> behavior.

I'll insist on the fact we cannot rely on 'number of commit' because 
revset is not "predicable enough".

Basic user will start provided simple revsets with "non-predicable" 
result, and you should not expect them to be smart enough to add "first" 
like element to it until it suddenly break for unclear (to them reason) 
and stop trusting the tool.

Moreover, You have way to force the 'multiple -> one' way. But you have 
no way to go the other way. Lets look at this command command:

- hg fold --exact 'draft() and ::mybook'

Current behavior (with --exact)

revs | result
-------------
  0-1 | abort 'nothing to fold here'
  2+  | fold all revs together

This is a safe sensible and predictable behavior.

With 'auto detect revset size proposal'


revs | result
-------------
  0   | abort 'no rev'
  0-1 | fold 'revs::.'
  2+  | fold all revs together

This is unpredictable behavior that will blow in people face.

So, think of the children, do not relying on the size of the revset result.
Laurent Charignon - June 3, 2015, 12:25 a.m.
I have sent a V2 taking into account the requested changes.
Jordi, how do you feel about Pierre-Yves' argument for this patch?

Thanks,

Laurent

On May 31, 2015, at 1:03 PM, Pierre-Yves David <pierre-yves.david@ens-lyon.org<mailto:pierre-yves.david@ens-lyon.org>> wrote:



On 05/30/2015 02:28 AM, Gilles Moris wrote:
Le 30/05/2015 03:29, Pierre-Yves David a écrit :


On 05/28/2015 03:26 PM, Matt Mackall wrote:

[reordered]

> It seems to me that both --exact and --chain are unnecessarily

> complicated. We should really consider an interface that's simply:

>

>   hg fold start::end

>

> with no magic defaults.


Lets write some history here...

In the dawn of time, the behavior was:
 hg fold <revset>
-> fold everything in <revset> together.
 (This match the `hg fold start::end` from Matt.)

There was two issue with this UI:

1) It pretty much requires the knowledge of revset to be used
efficiently. This put the barrier of entry higher than necessary for a
fairly basic command.

2) The most common case turned out to be, I want to fold the last N
commits. This happen commonly when one is working toward something,
making frequent wip commit along the way to be able to easily go back
to a check point. So the common case was `hg fold X::.`

(This two principle seems important to: (1) do not requires revset
knowledge to ensure a low barrier of entry (2) default case should be
easy).


So, we move the default to :

 hg fold <rev>
-> fold everything between '.' and <rev>.

 hg fold --exact <revset>
 -> fold everything in the revset.

I think that putting the advanced use case of 'folding anywhere' is an
okay choice.

Most of mercurial command behave according the working directory parent

- commit -> make a commit as child as '.'
- amend -> add content to '.'
- uncommit -> remove content to '.'
- hg split -> split '.' into multiple changeset (in the future)
- diff -> show difference with '.'
- revert -> restore file as in '.'
- merge -> merge '.' with something else
- rebase -> rebase '.' somewhere else (by default)
- graft -> get a new commit on top of '.'
- histedit -> histedit from '.' to X
 (would be nice to have an '--exact' here actually)
- hg evolve -> evolve stuff related to '.'

So I think it at most sensible (and at best consistent) with the other
commands than the default involves the working copy.

[former message start]

hg fold 9 # will fold 9 and 10 together, unchanged

Ok.

hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error

What is the user story where this is what's wanted? If the answer is
"never" (which I suspect), then we should just make this do what's
expected: fold the specified versions with each other.

I believe "8+7" is only used here as an example. It is a place holder
for 'anycomplicatedrevset()'. In that case, the revset result could be
said "visually obvious" but the internal code have no clue about.

My personal philosophy is:

 "We should lever change behavior accord length of a revset result"

When I run a command with '::myfeature - public()' I dunno if this is
going to return 0, 1, 2 or N changeset. But I still want to be able to
build alias for it and run command without double checking revset
lengh. Therefore, command cannot change there behavior regarding
revset query result because that will blow in my face all the time.

hg fold 8 + 7 --chain # folds 7,8,9,10 together

Why would anybody type that rather than:

 hg fold --chain 7

CF, previous comment. Nobody is going to type 7+8. But revset result
will be 7+8

Adding + 8 doesn't add any additional info except maybe "I'm trying to
do something different and am about to have a sad."


I am not convinced that it needs 2 flags, or even 1.

Forgetting about the current UI, we could expect that providing a single
commit would fold up to the working dir. If a complex revset is
provided, I guess the power user could do "first(revset)". If we really
want a flag for safety, we could use -f/--from: "hg fold -f 7".
Then if a revset yields multiple commits, I would expect the --exact
behavior.

I'll insist on the fact we cannot rely on 'number of commit' because revset is not "predicable enough".

Basic user will start provided simple revsets with "non-predicable" result, and you should not expect them to be smart enough to add "first" like element to it until it suddenly break for unclear (to them reason) and stop trusting the tool.

Moreover, You have way to force the 'multiple -> one' way. But you have no way to go the other way. Lets look at this command command:

- hg fold --exact 'draft() and ::mybook'

Current behavior (with --exact)

revs | result
-------------
0-1 | abort 'nothing to fold here'
2+  | fold all revs together

This is a safe sensible and predictable behavior.

With 'auto detect revset size proposal'


revs | result
-------------
0   | abort 'no rev'
0-1 | fold 'revs::.'
2+  | fold all revs together

This is unpredictable behavior that will blow in people face.

So, think of the children, do not relying on the size of the revset result.

--
Pierre-Yves David
Durham Goode - June 3, 2015, 3:32 a.m.
On 5/31/15 1:03 PM, Pierre-Yves David wrote:
>
>
> On 05/30/2015 02:28 AM, Gilles Moris wrote:
>> Le 30/05/2015 03:29, Pierre-Yves David a écrit :
>>>
>>>
>>> On 05/28/2015 03:26 PM, Matt Mackall wrote:
>>>
>>> [reordered]
>>>
>>> > It seems to me that both --exact and --chain are unnecessarily
>>> > complicated. We should really consider an interface that's simply:
>>> >
>>> >   hg fold start::end
>>> >
>>> > with no magic defaults.
>>>
>>> Lets write some history here...
>>>
>>> In the dawn of time, the behavior was:
>>>   hg fold <revset>
>>>  -> fold everything in <revset> together.
>>>   (This match the `hg fold start::end` from Matt.)
>>>
>>> There was two issue with this UI:
>>>
>>> 1) It pretty much requires the knowledge of revset to be used
>>> efficiently. This put the barrier of entry higher than necessary for a
>>> fairly basic command.
>>>
>>> 2) The most common case turned out to be, I want to fold the last N
>>> commits. This happen commonly when one is working toward something,
>>> making frequent wip commit along the way to be able to easily go back
>>> to a check point. So the common case was `hg fold X::.`
>>>
>>> (This two principle seems important to: (1) do not requires revset
>>> knowledge to ensure a low barrier of entry (2) default case should be
>>> easy).
>>>
>>>
>>> So, we move the default to :
>>>
>>>   hg fold <rev>
>>>  -> fold everything between '.' and <rev>.
>>>
>>>   hg fold --exact <revset>
>>>   -> fold everything in the revset.
>>>
>>> I think that putting the advanced use case of 'folding anywhere' is an
>>> okay choice.
>>>
>>> Most of mercurial command behave according the working directory parent
>>>
>>> - commit -> make a commit as child as '.'
>>> - amend -> add content to '.'
>>> - uncommit -> remove content to '.'
>>> - hg split -> split '.' into multiple changeset (in the future)
>>> - diff -> show difference with '.'
>>> - revert -> restore file as in '.'
>>> - merge -> merge '.' with something else
>>> - rebase -> rebase '.' somewhere else (by default)
>>> - graft -> get a new commit on top of '.'
>>> - histedit -> histedit from '.' to X
>>>   (would be nice to have an '--exact' here actually)
>>> - hg evolve -> evolve stuff related to '.'
>>>
>>> So I think it at most sensible (and at best consistent) with the other
>>> commands than the default involves the working copy.
>>>
>>> [former message start]
>>>
>>>>> hg fold 9 # will fold 9 and 10 together, unchanged
>>>>
>>>> Ok.
>>>>
>>>>> hg fold 8 + 7 # before was folding 7,8,9,10, now prints an error
>>>>
>>>> What is the user story where this is what's wanted? If the answer is
>>>> "never" (which I suspect), then we should just make this do what's
>>>> expected: fold the specified versions with each other.
>>>
>>> I believe "8+7" is only used here as an example. It is a place holder
>>> for 'anycomplicatedrevset()'. In that case, the revset result could be
>>> said "visually obvious" but the internal code have no clue about.
>>>
>>> My personal philosophy is:
>>>
>>>   "We should lever change behavior accord length of a revset result"
>>>
>>> When I run a command with '::myfeature - public()' I dunno if this is
>>> going to return 0, 1, 2 or N changeset. But I still want to be able to
>>> build alias for it and run command without double checking revset
>>> lengh. Therefore, command cannot change there behavior regarding
>>> revset query result because that will blow in my face all the time.
>>>
>>>>> hg fold 8 + 7 --chain # folds 7,8,9,10 together
>>>>
>>>> Why would anybody type that rather than:
>>>>
>>>>   hg fold --chain 7
>>>
>>> CF, previous comment. Nobody is going to type 7+8. But revset result
>>> will be 7+8
>>>
>>>> Adding + 8 doesn't add any additional info except maybe "I'm trying to
>>>> do something different and am about to have a sad."
>>>
>>
>> I am not convinced that it needs 2 flags, or even 1.
>>
>> Forgetting about the current UI, we could expect that providing a single
>> commit would fold up to the working dir. If a complex revset is
>> provided, I guess the power user could do "first(revset)". If we really
>> want a flag for safety, we could use -f/--from: "hg fold -f 7".
>> Then if a revset yields multiple commits, I would expect the --exact
>> behavior.
>
> I'll insist on the fact we cannot rely on 'number of commit' because 
> revset is not "predicable enough".
>
> Basic user will start provided simple revsets with "non-predicable" 
> result, and you should not expect them to be smart enough to add 
> "first" like element to it until it suddenly break for unclear (to 
> them reason) and stop trusting the tool.
>
> Moreover, You have way to force the 'multiple -> one' way. But you 
> have no way to go the other way. Lets look at this command command:
>
> - hg fold --exact 'draft() and ::mybook'
>
> Current behavior (with --exact)
>
> revs | result
> -------------
>  0-1 | abort 'nothing to fold here'
>  2+  | fold all revs together
>
> This is a safe sensible and predictable behavior.
>
> With 'auto detect revset size proposal'
>
>
> revs | result
> -------------
>  0   | abort 'no rev'
>  0-1 | fold 'revs::.'
>  2+  | fold all revs together
>
> This is unpredictable behavior that will blow in people face.
>
> So, think of the children, do not relying on the size of the revset 
> result.
>
If a user specifies a single commit (via revset, or node, or whatever), 
can we error out and say "you only specified one commit. did you mean: 
hg fold X::." ?  That keeps the syntax precise (fold exactly what I say, 
don't compute any closures), and teaches the user about revsets.
Durham Goode - June 3, 2015, 3:35 a.m.
On 6/2/15 8:32 PM, Durham Goode wrote:
>
>
> On 5/31/15 1:03 PM, Pierre-Yves David wrote:
>>
>>
>> On 05/30/2015 02:28 AM, Gilles Moris wrote:
>>> Le 30/05/2015 03:29, Pierre-Yves David a écrit :
>>>
>>> I am not convinced that it needs 2 flags, or even 1.
>>>
>>> Forgetting about the current UI, we could expect that providing a 
>>> single
>>> commit would fold up to the working dir. If a complex revset is
>>> provided, I guess the power user could do "first(revset)". If we really
>>> want a flag for safety, we could use -f/--from: "hg fold -f 7".
>>> Then if a revset yields multiple commits, I would expect the --exact
>>> behavior.
>>
>> I'll insist on the fact we cannot rely on 'number of commit' because 
>> revset is not "predicable enough".
>>
>> Basic user will start provided simple revsets with "non-predicable" 
>> result, and you should not expect them to be smart enough to add 
>> "first" like element to it until it suddenly break for unclear (to 
>> them reason) and stop trusting the tool.
>>
>> Moreover, You have way to force the 'multiple -> one' way. But you 
>> have no way to go the other way. Lets look at this command command:
>>
>> - hg fold --exact 'draft() and ::mybook'
>>
>> Current behavior (with --exact)
>>
>> revs | result
>> -------------
>>  0-1 | abort 'nothing to fold here'
>>  2+  | fold all revs together
>>
>> This is a safe sensible and predictable behavior.
>>
>> With 'auto detect revset size proposal'
>>
>>
>> revs | result
>> -------------
>>  0   | abort 'no rev'
>>  0-1 | fold 'revs::.'
>>  2+  | fold all revs together
>>
>> This is unpredictable behavior that will blow in people face.
>>
>> So, think of the children, do not relying on the size of the revset 
>> result.
>>
> If a user specifies a single commit (via revset, or node, or 
> whatever), can we error out and say "you only specified one commit. 
> did you mean: hg fold X::." ?  That keeps the syntax precise (fold 
> exactly what I say, don't compute any closures), and teaches the user 
> about revsets.
Heck, if X is the immediate parent, you could even suggest "hg fold 'X + 
.'" so it's extremely obvious what the correct syntax is (no 
understanding of :: necessary)
Pierre-Yves David - June 9, 2015, 12:08 a.m.
On 06/02/2015 08:35 PM, Durham Goode wrote:
>
>
> On 6/2/15 8:32 PM, Durham Goode wrote:
>> If a user specifies a single commit (via revset, or node, or
>> whatever), can we error out and say "you only specified one commit.
>> did you mean: hg fold X::." ?  That keeps the syntax precise (fold
>> exactly what I say, don't compute any closures), and teaches the user
>> about revsets.
> Heck, if X is the immediate parent, you could even suggest "hg fold 'X +
> .'" so it's extremely obvious what the correct syntax is (no
> understanding of :: necessary)

I like the idea of customizing the error message instead of the 
behavior. It allow to provide useful information while not blowing up 
anything.

I would be pretty unhappy to expose random user to X::Y recommendation 
because they will screw it up a X:Y and get burned down. So the idea of 
X+. is also interesting (but won't work for a full stack).

So I like the ideas above and that should definitely goes to the wiki 
page that sums up the discussion. However, this does not address the 
issue of "the common case is more complicated that it should be, so I'm 
not 100% sold.
Pierre-Yves David - June 9, 2015, 7:58 p.m.
On 06/08/2015 05:08 PM, Pierre-Yves David wrote:
> I would be pretty unhappy to expose random user to X::Y recommendation
> because they will screw it up a X:Y and get burned down. So the idea of
> X+. is also interesting (but won't work for a full stack).

Thinking more about this, we could recommend `.~x` instead of `x::.`
Matt Mackall - June 9, 2015, 8:20 p.m.
On Tue, 2015-06-09 at 12:58 -0700, Pierre-Yves David wrote:
> On 06/08/2015 05:08 PM, Pierre-Yves David wrote:
> > I would be pretty unhappy to expose random user to X::Y recommendation
> > because they will screw it up a X:Y and get burned down. So the idea of
> > X+. is also interesting (but won't work for a full stack).

Do we allow folding non-linearly-related changesets?
Pierre-Yves David - June 9, 2015, 8:22 p.m.
On 06/09/2015 01:20 PM, Matt Mackall wrote:
> On Tue, 2015-06-09 at 12:58 -0700, Pierre-Yves David wrote:
>> On 06/08/2015 05:08 PM, Pierre-Yves David wrote:
>>> I would be pretty unhappy to expose random user to X::Y recommendation
>>> because they will screw it up a X:Y and get burned down. So the idea of
>>> X+. is also interesting (but won't work for a full stack).
>
> Do we allow folding non-linearly-related changesets?

This is unsupported yet (because this requires in memory rebasing, that 
we do not support yet).

I think we will want a way to support such folding (the same as we 
support non linear set in rebase).
Laurent Charignon - June 12, 2015, 8:25 p.m.
Looks like everyone agrees on the following:
- When specifying one commit 'x', we error out and recommend doing  `.~x`
- --exact becomes the default behavior

If nobody feels strongly against that, I will send a V3.

> On Jun 9, 2015, at 1:22 PM, Pierre-Yves David <pierre-yves.david@ens-lyon.org> wrote:
> 
> 
> 
> On 06/09/2015 01:20 PM, Matt Mackall wrote:
>> On Tue, 2015-06-09 at 12:58 -0700, Pierre-Yves David wrote:
>>> On 06/08/2015 05:08 PM, Pierre-Yves David wrote:
>>>> I would be pretty unhappy to expose random user to X::Y recommendation
>>>> because they will screw it up a X:Y and get burned down. So the idea of
>>>> X+. is also interesting (but won't work for a full stack).
>> 
>> Do we allow folding non-linearly-related changesets?
> 
> This is unsupported yet (because this requires in memory rebasing, that we do not support yet).
> 
> I think we will want a way to support such folding (the same as we support non linear set in rebase).
> 
> -- 
> Pierre-Yves David
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel
Pierre-Yves David - June 12, 2015, 8:36 p.m.
On 06/12/2015 01:25 PM, Laurent Charignon wrote:
> Looks like everyone agrees on the following:
> - When specifying one commit 'x', we error out and recommend doing  `.~x`

Actually this does work because it need the ::. (that I'm not fan of) 
(Yes I pointed at this .~x thing, but it was just wrong, afterall)

> - --exact becomes the default behavior

I'm still not convinced by that.

> If nobody feels strongly against that, I will send a V3.

I think we still need a summary on the EvolveUI wiki page before moving 
forward.

Patch

diff --git a/hgext/evolve.py b/hgext/evolve.py
--- a/hgext/evolve.py
+++ b/hgext/evolve.py
@@ -2263,7 +2263,9 @@ 
 
 @command('^fold|squash',
     [('r', 'rev', [], _("revision to fold")),
-     ('', 'exact', None, _("only fold specified revisions"))
+     ('', 'exact', None, _("only fold specified revisions")),
+     ('', 'chain', None, _('fold the chain of revisions between the given '
+                           'revisions and the parent of the working copy')),
     ] + commitopts + commitopts2,
     _('hg fold [OPTION]... [-r] REV'))
 def fold(ui, repo, *revs, **opts):
@@ -2308,6 +2310,14 @@ 
     revs = scmutil.revrange(repo, revs)
 
     if not opts['exact']:
+        if len(revs) > 1 and not opts['chain'] and not repo['.'].rev() in revs:
+            ui.write_err(_('multiple revisions specified not including the'
+            ' parent of the working.\n'
+            'Please use one of:\n'
+            '   --exact to fold exactly these revisions\n'
+            '   --chain to fold the chain from these revisions upto the parent'
+            'of the working copy\n'))
+            return 1
         # Try to extend given revision starting from the working directory
         extrevs = repo.revs('(%ld::.) or (.::%ld)', revs, revs)
         discardedrevs = [r for r in revs if r not in extrevs]
diff --git a/tests/test-evolve.t b/tests/test-evolve.t
--- a/tests/test-evolve.t
+++ b/tests/test-evolve.t
@@ -634,7 +634,14 @@ 
   $ hg fold -r 4 -r 6 --exact
   abort: cannot fold non-linear revisions (multiple roots given)
   [255]
-  $ hg fold 10 1
+Two revisions in the middle of the stack, ambiguous behavior
+  $ hg fold -r '4+5'
+  multiple revisions specified not including the parent of the working.
+  Please use one of:
+     --exact to fold exactly these revisions
+     --chain to fold the chain from these revisions upto the parentof the working copy
+  [1]
+  $ hg fold 10 1 --chain
   abort: cannot fold non-linear revisions
   (given revisions are unrelated to parent of working directory)
   [255]
@@ -642,14 +649,19 @@ 
   $ hg fold -r 0
   abort: cannot fold public revisions
   [255]
+
+Two revisions including the parent of the working copy
+  $ hg fold -r '6 + 10'
+  2 changesets folded
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg fold -r 5
-  3 changesets folded
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  2 changesets folded
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg fold 6 # want to run hg fold 6
   abort: hidden revision '6'!
   (use --hidden to access hidden revisions)
   [255]
-  $ hg log -r 11 --template '{desc}\n'
+  $ hg log -r 12 --template '{desc}\n'
   add 3
   
   
@@ -664,21 +676,21 @@ 
 
   $ hg up 4
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
-  $ hg fold --rev 4::11 --user victor --exact
+  $ hg fold --rev 4::12 --user victor --exact
   2 changesets folded
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ glog
-  @  12:d26d339c513f@default(draft) add 4
+  @  13:d26d339c513f@default(draft) add 4
   |
   | o  1:73d38bb17fd7@default(draft) add 1
   |/
   o  0:8685c6d34325@default(public) add 0
   
   $ hg log --template '{rev}: {author}\n'
-  12: victor
+  13: victor
   1: test
   0: test
-  $ hg log -r 12 --template '{desc}\n'
+  $ hg log -r 13 --template '{desc}\n'
   add 4
   
   
@@ -696,32 +708,32 @@ 
 
   $ hg olog
   4	: add 4 - test
-  11	: add 3 - test
+  12	: add 3 - test
 
 Test obsstore stat
 
   $ hg debugobsstorestat
-  markers total:                     10
-      for known precursors:          10
+  markers total:                     11
+      for known precursors:          11
       with parents data:              0
   markers with no successors:         0
-                1 successors:        10
+                1 successors:        11
                 2 successors:         0
       more than 2 successors:         0
       available  keys:
-                 user:               10
+                 user:               11
   disconnected clusters:              1
           any known node:             1
-          smallest length:           10
-          longer length:             10
-          median length:             10
-          mean length:               10
+          smallest length:           11
+          longer length:             11
+          median length:             11
+          mean length:               11
       using parents data:             1
           any known node:             1
-          smallest length:           10
-          longer length:             10
-          median length:             10
-          mean length:               10
+          smallest length:           11
+          longer length:             11
+          median length:             11
+          mean length:               11
 
 
 Test evolving renames
@@ -741,8 +753,8 @@ 
   1 changesets pruned
   1 new unstable changesets
   $ hg stab --any
-  move:[15] c
-  atop:[13] a
+  move:[16] c
+  atop:[14] a
   working directory is now at 3742bde73477
   $ hg st -C --change=tip
   A c
diff --git a/tests/test-tutorial.t b/tests/test-tutorial.t
--- a/tests/test-tutorial.t
+++ b/tests/test-tutorial.t
@@ -494,6 +494,8 @@ 
   
    -r --rev VALUE [+] revision to fold
       --exact         only fold specified revisions
+      --chain         fold the chain of revisions between the given revisions
+                      and the parent of the working copy
    -m --message TEXT  use text as commit message
    -l --logfile FILE  read commit message from file
    -d --date DATE     record the specified date as commit date