Merge on push?

Bill Barry after.fallout at gmail.com
Sat Jun 7 16:56:46 CDT 2008


I'd rather do the merge locally; perhaps an extension could do this (a 
shell script could be written fairly easily to do exactly this if you 
wanted to try):

hg push -f
while (multiple remote heads)
  hg pull
  hg merge
  if (merge successful locally)
    hg ci -m "automerge"
    hg push -f
  else
    fail (notify the user that conflicts need to be resolved before 
continuing)

But I don't think that really will work (there is too many edge cases). 
What if another user attempted to push at almost the same time? You 
could pull down a repository with a whole bunch of heads.

What I think would be better is a bound mode like bzr has (from here on 
I'm stealing ideas from bzr; they may already be available somewhere in 
hg, but I don't know about them). Default should be unbound (bzr 
defaults one way or another depending on how you get the initial repo 
and cloning is similar to the unbound way in bzr) and would behave 
exactly like it does now, but when in bound mode it would behave much 
more like a centralized repo such as svn does:

1. commits would fail if there is already a newer head in the remote 
repository (on the same named branch as you are on)
2. commits automatically and atomically push to the remote repository 
(the one which is bound to) [note 1]
3. update would automatically pull and attempt a merge (update would 
become an alias for fetch when in bound mode)
4. when binding, if the local head is different than the remote head, a 
pull and a merge would automatically be attempted locally and a message 
telling the user that a merge has been done and the working copy needs 
to be committed (or that the merge failed and needs to be completed; 
either way you would be in bound mode)

There should be a couple of additional commands to use for this:
hg bind [-f] [repo]
 - binds to repo (or to repo specified as push/pull repo in hgrc if not 
in command line)
 - will fail if the repositories are not similar (do not have some 
common parent or something like that; -f will bind anyways)
hg mode
 - displays "bound" or "unbound" depending on what mode the repo is in
hg unbind
 - switches out of bound mode
hg clone -b
 - creates a clone in bound mode (someone could also alias this to hg 
checkout if it were so desired)

This way hg would work almost exactly the same as svn does. A user who 
only ever works in bound mode only needs to know "hg ci", "hg up", and 
"hg clone -b". It seems to me that if someone were to write some sort of 
"autopush" extension (you would commit like: hg ci --autopush or 
something), all this would take is some other extension to create the 
bind, mode, and unbind commands and override the update and commit to be 
fetch and autopush. The extension could also add the -b param to clone 
to clone in bound mode.

1:
Perhaps the remote repo could be locked while the commit is happening; 
that would probably require the least amount of work to get this to 
work. Another way would be something like:
1. commit locally
2. push the commit
3. if a new head is to be created remotely undo the local commit and 
stop, leaving the working copy with the uncommitted work
4. otherwise complete the push



Roman Kennke wrote:
> Hi there,
>
> One of the most frequent complaints about Mercurial (probably even _the_
> most frequent complaint) is that it is so difficult to push stuff to
> remote repositories. While Mercurial is a distributed RCS, I think that
> the majority of projects still have a central repository that serves as
> a the basis for releases etc. At my workplace, we tend to do work using
> a mixed approach: we have one central repository, but developers pull
> stuff from each other anyway, i.e. in order to exchange patches that
> can't go into the master at this point, but need testing in a different
> context, etc.
>
> I think pushing to a central repository is a very important action, and
> I also think that it is unnecessarily complicated in Mercurial. The
> current situation is that when a developer tries to push, in almost all
> cases it aborts and he needs to pull && merge && commit and then push
> again (don't forget to update at some point too). I know, hg fetch can
> make all this a little easier, but still, it is additional overhead at
> the side of the developer. The worst thing is, that it is possible that
> after the fetch sequence, the push can fail again, when another
> developer managed to push something in between. This isn't much of a
> problem in projects with few developers or when developers tend not to
> push very often. However, for large scale projects with a push-often
> policy, this is really bad.
>
> I know that there are ways around this using different workflows, for
> example, large projects could split up the central repository into a
> hierarchy of group repositories (like in OpenJDK), or it could use a
> pull-only approach, where a release maintainer pulls the patches he
> wants in the master repo from the developer repositories. But this is
> not my point, my point is that when a group _wants_ to use the push
> approach, then it makes no sense to make that so hard.
>
> I'd like to propose an extension to the push command. I imagine an
> option --merge and maybe a configuration option for use in ~/.hgrc which
> makes push try a merge on the remote side if necessary. hg push --merge
> would then try to perform a non-interactive merge and commit on the
> remote repository, when the push would create an additional head. This
> should fail when the changes touch files that have been touched by other
> changesets since their 'branch-point'. This is more or less the
> behaviour of more traditional RCSes. I know, there is a chance that this
> results in a broken tree even when there are no overlapping changes, but
> experience with more traditional RCSes (CVS and Subversion, maybe other
> DRCSes, dunno about them) shows that such cases are very rare in a
> reasonable structured project.
>
> Does that make any sense? Or is there something I just don't see from my
> POV? I think Mercurial is otherwise a very scalable and usable DRCS, but
> this single point is a real pain, and truly hinders adoption (at least,
> I'm having a hard time defending HG among my coworkers and developer
> friends at a couple of projects).
>
> Cheers, Roman
>
>   



More information about the Mercurial mailing list