Simple usage pattern seems problematic ?

Giorgos Keramidas keramida at ceid.upatras.gr
Sun Jan 23 05:49:42 CST 2011


On Sat, 22 Jan 2011 14:52:45 +0200, Maxim Veksler <maxim at vekslers.org> wrote:
> Our work flow is the most simplistic you can think of. Developer
> seeking to make a change to the project checks it out from bitbucket,
> makes his changes either using MercurialEclipse 1.7.1 or command line
> hg which is usually followed by a commit. Should this be a quick patch
> change the commit is followed by an immediate push. None of the
> projects use "multiple heads" / tags. All the repositories always
> remain at default, tip.

Hi Maxim,

First of all congratulations on choosing Mercurial & Bitbucket.  The
combination of these two really *rocks* for collaborative work :-)

> The problems:
>
>    - 2 developers working on the same project. Developer1 does a push.
>      Developer 2 seeking to apply developer1 changes locally has to
>      follow this sequence of actions: (1) pull, (2) update and (3)
>      *merge *followed by a (4) commit (of the merge). Please note that
>      I'm not talking about the situation where incoming changes cause
>      conflicts (situation which obviously requires manual resolution)
>      the described process is for a "clean" update where incoming
>      changes can be applied seamlessly.

If two people work on different clones it's actually safer to commit the
local changes _first_ and _then_ pull from others.  You are probably
thinking of something like "svn update", where you can have local stuff
that is uncommitted and run "svn update" to merge with the upstream
code, but this is not safe.

Consider the case of an "svn update" that has to merge conflicts in
several files.  One of them is too complex to merge in less than one
minute.  So you keep your editor open with some of the local conflicts
resolved.  You do save the work-in-progress merge now and then to avoid
losing it.  At that point power goes out.  You lose the open editor
buffer and the file in your working space is a "mix" of stuff half-way
between the original local state and the fully resolved state.

Can you go back to the local-only state?  Nope.  It's gone.  And it has
not been stored anywhere.  All you can do is re-edit the half merged
file and hope that you can make sense of the half-done merge.

The approach of Mercurial, on the other hand, is different.  Before you
pull changes from others you *commit* your local stuf to a changeset of
the local tree.  When you pull, the remote changes show up as 'new
heads', e.g. with a fork of the local history like this:

               L1    L2
    o --- o --- o --- o
          \
           \--- o --- o --- o --- o --- o
               R1    R2    R3    R4    R5

where L1 and L2 are your own local commits, and R1 .. R5 are the changes
of Developer 2 who managed to push his commits first.

When you want to merge your own local code with Developer 2 work, you
can just run:

        hg update --clean L2
        hg merge R5

If the merge fails, is interrupted, doesn't work very well, or you
cannot understand how to resolve the conflicts, that's ok...

  - You can go back at the local-only state by typing:

        hg update --clean L2

  - You can check-out the clean Developer 2 code, to see if his version
    works, without having to worry if your local changes might break
    something he did:

        hg update --clean R5

  - You can repeat the merge starting from a "clean slate":

        hg update --clean L2
        hg merge R5

  - You can try a different merge tool, to see if it helps you make
    sense of the conflicts:

        hg update --clean L2
        env HGMERGE='/home/keramida/bin/mergetool' merge R5

Note that:

    (1) At *no* point were you left with a half-done merge that you
        cannot recover from.  It's always possible to go to the state of
        the code before the merge, either _yours_ or _other_.

    (2) You can go backand forth between your local changes and the
        changes of Developer 2 very easily.

    (3) You can repeat the merge as many times as you want, starting
        always from a clean slate.

So, you are right that Mercurial works 'better' if you _commit_ your
local stuff first and _then_ pull from other people.  But there are very
good reasons why this is the recommended workflow.

>    Is the described flow normal?
>    Is this the expected working method with mercurial?
>    Can we have a more simple method to update the local repository without
>    having to do merge, commit on each update?

Yes, once you get more experience with Mercurial extensions, you can
probably use the Rebase extension or the Shelve extension to keep some
of your stuff as local-only changes.

For now, keep it simple:

    Commit first - pull - merge - verify - repeat...

> The merge & commit are specifically problematic because this is
> reflected on the bitbucket diff view, where it shows the developer
> committing the merge as the one actually responsible for the changes,
> which is obviously not the case.

It also shows the parent changesets, e.g. where the changes came from.
The committer who pushes a *merge* is indeed responsible for the changes
of the merge.  He is supposed to have verified that the merged code
works as expected, before pushing...

> - Developer can't update his local workspace without committing all of
>   his local changes first. Why this constraint exists? The most
>   obvious mode where this collides is when you change configuration
>   files for your local development... You obviously don't need these
>   changes to be pushed into the repository.

The problem of personalized configuration is not new to Mercurial.  It
also exists in other version control systems.  The simple solution to
this problem is "don't version your config files".  Otherwise a commit
may accidentally push personal settings, e.g. when someone is tired or
distracted and types:

        svn commit -m 'Update libfoo to frob the gnats faster.' .
        hg commit -m 'Update libfoo to frob the gnats faster.' .

You should look at the possibility of having the actual configuration
files be _generated_ from stuff that exists in your versioned tree, so
that developers can have their own untracked personal configuration but
the main configuration template *is* versioned.

Cheers,
Giorgos



More information about the Mercurial mailing list