hg evolve command usability problems

Matt Harbison mharbison72 at gmail.com
Sat Jan 17 01:54:17 UTC 2015


> On Thu, 15 Jan 2015 18:24:32 -0500, Angel Ezquerra
> <angel.ezquerra at gmail.com> wrote:
>  TL;DR: I tried to use evolve. The experience was... not great.

I've had a pretty good experience so far, having not run into many sharp  
corners.  I'm still trying to get my mind around some stuff, and probably  
learned some wrong stuff, so don't take any of this as the absolute truth.

BTW, recent versions of the thg gui have been doing a great job helping to  
visualize some rather complex scenarios I've gotten into lately.  So a big  
thanks to all involved in pushing forward noticeable evolve related  
improvements in it in the last few releases.  I always watch that in the  
background while evolving so I can see how the graph is changing.

> I have recently had to use the hg evolve command to evolve several
> revisions on one of the patch series that I have recently sent to the
> list. The series had 6 revisions A-B-C-D-E-F. Only revisions A, C and
> E were taken (as A', C' and E' on the mercurial repo). When I pulled
> from mercurial's main repo I got A', C' and E', which made A, C and E
> obsolete. This also made B, D and F unstable. I supposed that using
> evolve to evolve B, D and F would be easy but boy was I wrong! It was
> much harder and error prone than I suspected. So this email will try
> to explain the problems I faced to see if we can improve things.

I think in this case, you don't want the evolve command at all.  Lately  
I've been rebasing the series that I'm working with onto tip, after I  
pull.  So something like 'hg rebase -s B -d tip' after you pulled in  
A'-C'-E'.  You then end up with A'-C'-E'-B'-D'-F', because rebase drops  
the obsolete commits instead of carrying them along.  (It's probably  
content based instead of obsolete marker based, so IDK what happens if  
say, C was tweaked in flight.  You might end up resolving something,  
and/or getting a remnant of C on top of B'.)  The proper obsolete markers  
are added for B, D and F.  But this skips the part where you evolve B onto  
A', and then end up having to rebase it anyway as you noted below.

> Before I start, note that I am aware that perhaps a lot of these
> problems are not really problems and are just due to my lack of
> understanding of the way evolve works. However, even if that is the
> case perhaps this is an indication that there is a UI problem in
> addition to a user problem?
>
> The main problem that I've got is that the evolve command is too smart
> and too dumb at the same time. It chooses which revision to evolve and
> where to move it to. There is very little control over what the
> command will do. In fact, since I cannot tell for sure what it will do
> in advance I normally do hg evolve --dry-run to see if what it is
> going to do makes sense or is what I really want to do (this is
> perhaps the first problem).

I think you choose what the command does, albeit rather subtly.  I think  
the way to explain what I've seen is that when you 'hg evolve', it looks  
up the precursor for the commit you're currently updated to, and then  
moves that precursor's first child.  Maybe there's more to it, and I've  
just fallen into a narrow routine.

I've on occasion wanted to evolve something other than that first child,  
in which case I just rebase.  For example, I tend to hack on something for  
a few commits, realize it may be a dead end, update back to the original  
commit and try something else- but not prune the original anonymous branch  
in case I need to reference it.  When that original parent commit gets  
accepted upstream and obsoleted, evolve will want to take the first commit  
in that first series, which is not usually what I want.

I think there's a bug written for this that's marked 'easy', but I haven't  
had time to really look at this recently.  Once I realized I could rebase  
and not screw up evolve, it was much less painful.

> In addition:
>
> - I updated to A and did hg evolve --dry-run. The command proposed to
> evolve D but I was expecting it to evolve B! I had to update to the
> parent of A for evolve to propose to evolve B.

Were you on A or A'?  Shouldn't you be evolving from A'?  I'd expect it to  
move B too though.

> - It is not possible to choose where the evolved revision is placed.
> If for example you want to rebase the revision to the head of your
> branch you must first evolve and then rebase.

I'm not sure that evolve should let you put something to a random place.   
Rebase already does that :-).  I think evolve is for gradual changes-  
amending something and then fixing up its descendants.  Rebase is still  
what you want for more radical changes like updating your local work on  
top of a bunch incoming changes IMHO.

> - After you evolve, the working directory points to the evolved
> revision. If you then do hg evolve again you get a "nothing to evolve"
> message! You must update back to where you were before, and then
> evolve again, but then the evolve target is not always what you want.

It sounds like the commit you were on before the evolve command had  
several immediate children (as opposed to a chain of X-Y-Z) that were  
unstable?  I know when I amend something a few revisions back in a linear  
branch, I can just continuously 'hg evolve' to stablize the rest of the  
branch without updating anywhere.

> - After I evolved a B (getting B' on top of A') I wanted to evolve D.
> But D became D' on top of C', so now I had two new heads, B' and D'. I
> realized my mistake (I should have rebased B' on top of C') so I
> decided to strip D' to start over. However D was no longer marked as
> unstable, just obsolete. So I could not evolve it again.
> - I have no idea what would happen if a revision had two unstable
> children and I ran hg evolve. Would it evolve both of them? The first
> one? Why can't I just choose one of them?

I think each evolve command only ever does one at a time.  I know there  
was a debate about doing more than one and/or an --all flag on the ML  
awhile back.  I'm guessing it would take the unstable child with the  
lowest revision, and then you would have to update back to evolve the  
second child.  Without an update back, it will continue to evolve the  
branch you are on, if anything else there is unstable.

> It is hard for me to really explain the problems that I faced. Perhaps
> it is a matter of me not really understanding evolve, but I felt as if
> the tool were fighting me. It took me way longer to do what I wanted
> to do than if I had just used graft, rebase or mq. I think the
> changeset evolution concept is very powerful but I find that the
> current UI is confusing and hard to use :-(
>
> Also, the fact that you do not directly chose which revision you want
> to evolve, seems to make the evolve command very GUI unfriendly.
>
> I think that I would be happier with a more graft or rebase-like UI,
> where I could explicitly choose the first unstable revision that I
> want to evolve (rather than the revision above which evolve will look
> for troubles) and the target.
>
> Sorry for the negative email, but I think this is really confusing and
> hard to use.
>
> Angel

--Matt



More information about the Evolve-testers mailing list