New evolve docs, take 2: 3/3: sharing.rst

Greg Ward greg at gerg.ca
Sat Jun 7 16:09:40 UTC 2014


Sorry for the delay in getting back to this. I've been working on
making the user guide the best I could. Now moving on to the sharing
guide.

On 29 May 2014, Pierre-Yves David said:
> On 05/28/2014 11:36 AM, Greg Ward wrote:
> >.. Copyright © 2014 Greg Ward <greg at gerg.ca>
> >
> >------------------------------
> >Evolve: Shared Mutable History
> >------------------------------
> >
> >Once you have mastered the art of mutable history in a single
> >repository, you might want to move up to the next level: *shared*
> >mutable history. ``evolve`` lets you push and pull draft changesets
> >between repositories along with their obsolescence markers. This opens
> >up a number of interesting possibilities.
> >
> >The most common scenario is a single developer working across two
> >computers.
> 
> That is a fairly common case, not sure this is the -most- common.
> Sharing changeset for review is a highly common usage too.

1) It's impossible to know what the most common use cases are. I still
   think starting out with "single developer, two repos" is good
   because it's the *simplest* use case. Maybe I should say "simple"
   and "advanced" rather than "common" and "uncommon".

2) Code review sounds like a good example.  I've never used evolve for
   review myself, so I'll have to figure out a workflow and document
   it. How hard can it be? ;-)

> >Say you're working on code that must be tested on a remote
> >test server, probably in a rack somewhere, only accessible by SSH, and
> >running an “enterprise-grade” (out-of-date) OS. But you probably
> >prefer to write code locally: everything is setup the way you like it,
> >and you can use your preferred editor, IDE, merge/diff tools, etc.
> 
> Out-of-topic-note: All the machine I use for testing are non-evolve
> enabled "sink" repo where I force push changeset I forged locally.
> The repo is non-publishing, but evolve is disabled. One of the
> reason is that obsolescence marker exchange used to be super slow
> and that I never edit a single file on those machine.

I'm not interested in describing how things *used* to be. It's better
now, so why dwell on the past? (Personally, I enable evolve on both
ends, so I can amend either locally or on the remote test server.
Works like a charm.)

> >Setting things up
> >-----------------
> >
> >We'll work an example with three local repositories, although in the
> >real world they'd most likely be on three different computers. First,
> >the public repository is where tested, polished changesets live, and
> >it is where you push/pull changesets to/from the rest of your team. ::
> >
> >   $ hg init public
> >
> >We'll need two clones where work gets done::
> >
> >   $ hg clone -q public test-repo
> >   $ hg clone -q test-repo dev-repo
> 
> Not fan of the `-q` here. Should either be kept verbose (prefered?)
> or --quiet

Hmmmm. I'm not aware of any other Mercurial docs that use long options
in favour of short options. Why should the evolve docs be special?

> >The key to making this whole thing work is to make ``test-repo``
> >non-publishing::
> >
> >   $ cat >> test-repo/.hg/hgrc <<EOF
> >   [phases]
> >   publish = false
> >   EOF
> 
> Please point to `hg config --edit --local` instead

OK. It looks to me like the best the docs can say is

  The key to making this whole thing work is to make ``test-repo``
  non-publishing by editing the repository config file::

    $ hg config --edit --local

  and then adding ::

    [phases]
    publish = false

In other words, I don't see any way to semi-automatically add a chunk
of text to .hg/hgrc. It would be nice if we could do something like
this:

  $ hg config --append --local <<EOF
  [phases]
  publish = false
  EOF

> >At this point, ``dev-repo`` and ``test-repo`` have the same changesets
> >in the same phases:
> >
> >   [figure SG01: rev 0:0dc9 public, rev 1:f649 draft, same on both repos]
> >
> >(You may notice a change in notation from the user guide: now
> >changesets are labelled with their revision number and the first four
> >digits of the 40-digit hexadecimal changeset ID. Mercurial revision
> >numbers are never stable when working across repositories, especially
> >when obsolescence is involved. We'll see why shortly.)
> 
> To be fair, I would be much happier if we dropped the revision
> number totally. Using a good description is usually the way to go.
> relying on short hash when required

Hmmm. I'm strongly in favour of using revnums in the user guide,
because someone running the examples at home will get the same
revnums, and revnums are nice, familiar, and monotonically increasing.
And they're safe to use because everything in the user guide is in one
repo. Finally, gaps in the revnum sequence are a nice hint about
hidden changesets.

In the sharing guide, obviously we have to use changeset IDs, so we
lose the "play along at home and get the same results" property. But
showing both revnums and changeset IDs means "OK, at least you get
half of the same results: your changeset IDs will differ, but your
revnums should be the same". And they're still monotonically
increasing and provide hints about hidden changesets.

So that's why the sharing guide uses "0:0dc9" notation. I've thought
carefully about this; you'll have to work pretty hard to change my
mind. ;-)

> >Now let's switch to ``test-repo`` to test our change::
> >
> >   $ cd ../test-repo
> >   $ hg update
> >
> >Don't forget to ``hg update``! Pushing only adds changesets to a
> >remote repository; it does not update the working directory (unless
> >you have a hook that updates for you).
> 
> link to said hook?

Hmmm. Maybe. Feels like a gratuitous external link to me. Trying to
keep the reader focused on evolve, not hopping off to irrelevant stuff
like hooks.

> >Let's resynchronize::
> >
> >   $ cd ../dev-repo
> >   $ hg pull -u
> >
> >As seen in figure 3, this transfers the new changeset *and* the
> >obsolescence marker for revision 1. However, it does *not* transfer
> >the temporary amend commit, because it is obsolete. Push and pull
> >transfer obsolesence markers between repositories, but they do not
> >normally transfer obsolete changesets.
> 
> You should not talk about the temporaty amend commit. It will go
> away. If you want a good example of non exchanged changeset. Double
> amend and point that the first amend result is omitted.

When temporary amend commits go away, let's remove them from the docs.
I strongly believe the docs should describe the system as it exists,
warts and all. Anybody playing along at home, running "hg --hidden
log", will see those temporary amend commits. If they are not
mentioned in the docs, the poor reader is going to think "did I do
something wrong?" or "is this a bug?".

> >
> >   [figure SG03: dev-repo grows new rev 2:60ff, marks 1:f649 obsolete]
> >
> >Because of this deliberately incomplete synchronization, revision
> >numbers in ``test-repo`` and ``dev-repo`` are no longer consistent. We
> >*must* use changeset IDs.
> 
> I'm parted. On one hand I really would like to see revision number
> phased out. On the second hand you mention them to point they are
> useless.

Revnums are not useless! They are inconsistent between repos, but that
doesn't stop people from using them *within a single repo*. There's
nothing wrong with that. They're a perfectly useful feature that
increases Mercurial's usability. They're just not universally
applicable.

> >Getting into trouble
> >--------------------
> >
> >Mercurial with ``evolve`` is a powerful tool, and using powerful tools
> >can have consequences. (You can cut yourself badly with a sharp knife,
> >but every competent chef keeps several around. Ever try to chop onions
> >with a spoon?)
> >
> >In the user guide, we saw examples of *unstable* changesets, which are
> >the most common type of troubled changeset. (Recall that a
> >non-obsolete changeset with obsolete ancestors is unstable.)
> 
> You should probably demonstrate easy occurence of unstable when you
> exchange.

Hmmm, OK. Bit of overlap with the user guide, but learning new
concepts is hard and often takes some repetition. OK, I'll do it.

> >Now Bob has a bad idea: he decides to pull whatever Alice is working
> >on and tweak her bug fix to his taste::
> >
> >   $ cd ../bob
> >   $ hg pull -q -u ../alice
> >   $ echo 'Fix.' > file2
> >   $ hg amend -q -A -m 'fix bug 15 (amended)'
> >
> >(Note the lack of communication between Alice and Bob. Failing to
> >communicate with your colleagues is a good way to get into trouble.
> >Nevertheless, ``evolve`` can usually sort things out, as we will see.)
> 
> I think the doc should insist sooner about communication and well
> behaving when sharing with other people.

Yeah. Right now, I'm thinking of adding a section on using evolve for
code review between Alice and Bob *before* the section that introduces
divergent and bumped changesets. I'll introduce the "trouble" section
by saying "when Alice and Bob fail to communicate, here's what can
happen".

> >
> >Divergent changesets
> >--------------------
> 
> bumped is fairly rare, I would put divergent explanation before
> bumped explanation

OK.

> >Here's where things change from the "bumped" scenario above: this
> >time, the original author (Bob) decides to amend his changeset too. ::
> >
> >   $ cd ../bob
> >   $ echo 'better (bob)' >> file1
> >   $ hg amend -u bob -m 'fix bug 24 (v2 by bob)'
> >
> >At this point, the divergence exists, but only in theory: Bob's
> >original changeset, 3:fe81, is obsolete and has two successors. But
> >those successors are in different repositories, so the trouble is not
> >visible to anyone yet. It will be as soon as one of our players pulls
> >from the other's repository. Let's make Bob the victim again::
> >
> >   $ hg pull -q -u ../alice
> >   not updating: not a linear update
> >   (merge or update --check to force update)
> >   2 new divergent changesets
> 
> 1. you should use long option in documenation (--quiet, --update).

Why? Where's the precedent? Bryan's book doesn't use long options.
hginit.com mostly uses short options. The Tutorial* pages in
Mercurials' wiki use short options.

> 2. second I would not recommend --update to pull.

Why not? Universally, or just in this instance?

> >
> >The “not a linear update” is our first hint that something is wrong,
> >but of course “2 new divergent changesets” is the real problem. Figure
> >9 shows both problems.
> >
> >   [figure SG09: bob's repo with 2 heads for the 2 divergent changesets, 5:fc16 and 6:694f; wc is at 5:fc16, hence update refused; both are successors of obsolete 3:fe81, hence divergence]
> >
> >Now we need to get out of trouble. Unfortunately, a `bug`_ in
> >``evolve`` means that the usual answer (run ``hg evolve --all``) does
> >not work.
> 
> 1. You should craft your demo so that `hg evolve` is able to work

I cooked up the simplest possible case of divergence that I could
think of. If you can suggest a different way to create divergent
changesets that evolve *can* handle, please tell me! (I see a possible
candidate in test-stabilize-result.t: I'll try to adapt that, or
something else in existing tests.)

> 2. It is not a bug. Just plain case of "the code did not wrote
> himself in the middle of the night"

I'm taking the end user's point of view: the software does not behave
as expected, therefore it's a bug. Only the original developer would
reply "no, no, that's an unimplemented feature!". ;-)

> Consider sending a patch if you
> have frequent need of it.

No, I've never experienced divergence apart from the artificial
example I cooked up for the documentation.

> >Bob has to figure out the solution on his own: in this case,
> >merge. To avoid distractions, we'll set ``HGMERGE`` to make Mercurial
> >resolve any conflicts in favour of Bob. ::
> 
> 1. Advertise `--config ui.merge=<BLA>` instead
> 2. Consider sending a patch for `--tool` for evolve

I like #2. Are there any other evolve commands that could invoke a
merge tool?

> >One annoying difference is that
> >Mercurial thinks the two divergent changesets are still divergent,
> >which you can see with a simple revset query::
> >
> >   $ hg log -q -r 'divergent()'
> >   5:fc16901f4d7a
> >   6:694fd0f6b503
> >
> >(That annoyance should go away when the bug is fixed.)
> 
> I'm really not keen to display the complexe and convoluted solution
> in the doc. Please go for the simple case where it works.

Like I said, this was the simplest way I could think of to create
divergence. If there is a simpler way that I missed, please tell me!

> >
> >Conclusion
> >----------
> >
> >Mutable history is a powerful tool. Like a sharp knife, an experienced
> >user can do wonderful things with it, much more wonderful than with a
> >dull knife (never mind a rusty spoon). At the same time, an
> >inattentive or careless user can do harm to himself or others.
> >Mercurial with ``evolve`` goes to great lengths to limit the harm you
> >can do by trying to handle all possible types of “troubled”
> >changesets. But having a first-aid kit nearby does not excuse you from
> >being careful with sharp knives.
> 
> Please mention that evolve is at an early stage and thing should
> improve over time.

I'm planning to add something along this lines to index.rst.

> >Mutable history shared by multiple developers is a scary place to go.
> >Imagine a professional kitchen full of expert chefs tossing their
> >favourite knives back and forth, with the occasional axe or chainsaw
> >thrown in to spice things up. If you're confident that you *and your
> >colleagues* can do it without losing a limb, go for it. But be sure to
> >practice a lot first before you rely on it!
> 
> You'll need animated gif to illustrate this ☺

Oh. Yes. Awesome. ;-)

       Greg
-- 
Greg Ward                            http://www.gerg.ca
<greg at gerg.ca>                       @gergdotca



More information about the Evolve-testers mailing list