[PATCH] Improved named branch support when pushing changesets

Henrik Stuart henrik.stuart at edlund.dk
Wed Mar 25 07:07:26 CDT 2009


BACKGROUND AND MOTIVATION

The current approach ignores named branches and only looks at the graph.
Some of the problems with this are demonstrated in the following example:

Upstream repo has: (0:a)
Downstream has:    (0:a) ---- (1:b)

So we have a single revision upstream on branch a, and created a new
branch, b, downstream. Doing a simple 'hg push' will work without
problems even though we are creating a new named branch!

Subsequently, another use has this downstream: (0:a) ---- (1:a)

Now this user _can't_ push without the --force option, even though he is
merely continuing the existing branch a. Our patch will reverse the need
for --force in the scenario above, among other things.

Another common example is when merging between two named branches. This
is the problem described in issue 736. It occurs quite often in
scenarios with development and stable branches in the same repo:

Upsteam has:

  (0:dev) ---- (1:dev)
          \--- (2:stable)

Someone merges stable into dev:

  (0:dev) ---- (1:dev) ------(3:dev)
          \--- (2:stable) --/

This can be pushed without --force (as it should).
Now someone else does some coding on stable (a bug fix, say):

  (0:dev) ---- (1:dev) ------(3:dev)
          \--- (2:stable) --/---------(4:stable)

This time we need --force to push. Our patch solves this issue as well.
The patch is included below, and can also be found (applied to crew tip)
here: http://hg.hstuart.dk/


APPROACH

The biggest problem with making these more intelligent branch decisions
is the lack of information that can be sent over the wire. It is
therefore necessary to extend the wire protocol (and add an extra
capability to stay compatible) in order to transmit the required
information. The information needed is essentially the dictionary that
_branchheads (in localrepo.py) returns, i.e. a map from branch to list
of heads.

We added a new method, branchmap, which just calls _branchheads, since
we need this map as a whole, and it's inefficient to call branchheads
once for each branch. It may be desirable to simply rename _branchheads
to branchmap (or some other name) and/or to deep or shallow-clone the
returned dictionary for safety.

We also extended the wire protocol with a similar function, 'branchmap',
which transmits this information. Finally, we have added the capability
'branchmap' to signal the presense of this function.

Apart from the above, the necessary code changes all take place in the
prepush method in localrepo.py and in an additional unit test file.


ALGORITHM

The following algorithm is used to determine whether or not to allow the
push. Any 'succeed' and 'fail' will stop the algorithm at that point.


  1. If --force is given, all checks are skipped. Succeed.

  2. If target is empty (no revisions), all checks are skipped. Succeed.

  3. For each named branch in source:

         1. If no branch heads in target, fail (use --force to create a
new branch).
         2. Figure out resulting target branch heads, and compare count
to current:

                1. If there are more resulting heads, fail (use --force
to create new heads).

  4. Succeed.


Note that steps 1 and 2 are identical to the current behavior and step
3.2 is essentially identical to the procedure used in the current code,
where it is applied to the entire graph instead of to each named branch
separately.

The counting method used in step 3.2 could be improved depending on
ambition and the level of complexity one is ready to endure in the code.
For most practical purposes, it seems adequate.

An option separate from --force could be introduced to allow the
creation of new named branches only. The problem with --force is that it
easily allows too much, e.g. too much for someone to want it in his or
her hgrc as a default for push.


--
Sune Foldager and Henrik Stuart
Edlund A/S
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0c2a3bf1e597.patch
Type: text/x-patch
Size: 16710 bytes
Desc: not available
Url : http://selenic.com/pipermail/mercurial-devel/attachments/20090325/ee786839/attachment.bin 


More information about the Mercurial-devel mailing list