RFC: dealing with dead, anonymous feature branches

Martin Geisler mg at aragost.com
Fri May 7 12:34:23 CDT 2010


Hi guys,

One of the very first times I talked about Mercurial here in Zurich, I
was asked what one should do if a set of changesets turned out to be
useless -- an abandoned feature branch. When I say "branch" in the
following, I'm not talking about named branches, I'm just talking about
topological branches, named or not.

I suggested a dummy merge, but that is a bad answer since Mercurial will
believe you when you say you've merged the branch and if you later
change your mind you wont get what you want.

One better answer could be: just delete your clone. However, this only
really works if the changesets have not been shared very far since
everybody has to remember to delete his clone.

The people I've talked to is also not very happy about setting up many
clones. Each working copy needs to be setup so they prefer a single.


My idea is a simple: we already have the --close-branch flag for commit
which inserts close=1 in the extra dictionary. Call such a head
"closed", other heads are "open". I propose that we do not push or pull
closed heads.

More precisely, when pushing from local to remote, we should

1) First, send all changesets that are ancestors of local open heads.

2) Then, send all changesets that descend from open remote heads.

(I hope we can do this in one go, I just split it in two for clarity.)

Examples are good, so consider these repositories:

  Local repository:              Remote repository:

  [A] --- [B] --- [C]            [A] --- [B]
     \
      [X] --- <Y>

We would normally push C and Y. By rule 1, we send C and get:

  Local repository:              Remote repository:

  [A] --- [B] --- [C]            [A] --- [B] --- [C]
     \
      [X] --- <Y>

By rule 2, we send nothing more.

The dead Y changeset is not lost, it is just not pushed or pulled
anywhere. If the remote has already "begun" the closed branch, then we
do want to push Y. Rule 2) ensures this since we push descendants of
remote open heads, i.e., Y. So

  Local repository:              Remote repository:

  [A] --- [B] --- [C]            [A] --- [B]
     \                              \
      [X] --- <Y>                    [X]

becomes

  Local repository:              Remote repository:

  [A] --- [B] --- [C]            [A] --- [B] --- [C]
     \                              \
      [X] --- <Y>                    [X]

after rule 1. Now X is an open remote head, so we push Y:

  Local repository:              Remote repository:

  [A] --- [B] --- [C]            [A] --- [B] --- [C]
     \                              \
      [X] --- <Y>                    [X] --- <Y>

The ordering of the two rules is important in this case:

  Local repository:              Remote repository:

  [A] --- [B] --- [C]            [A]
     \
      [X] --- <Y>

where rule 1 says that we first push B and C:

  Local repository:              Remote repository:

  [A] --- [B] --- [C]            [A] --- [B] --- [C]
     \
      [X] --- <Y>

and then A is suddenly no longer an open remote head, so X and Y is not
pushed by rule 2.


The idea is that this should allow me to experiment as much as I want,
and if I have shared the changes with others, then we can still
communicate the fact that the experiment has ended and that the branch
should be forgotten.

It is also trivial to cleanup a repository with many dead branches: just
clone it and you'll only get the open heads. We could also call them
"dead" or "alive" heads -- I sort of like the analogy with a tree where
some branches and twigs are dead... if you shake the tree then the dead
branches fall to the ground and the living branches are still up there.


I discussed this idea with Jan Sørensen from aragost and I had at some
point mentioned that we're "afraid" of many heads because the number of
heads is a term in the running time of some of our protocols. He
suggested that one could make a "canonical dead head", that is, merge
all dead heads until there is only a single dead head in the graph.

These synthetic merges should probably not be shown in the log. They are
only there to keep the number of heads down. Introducing a concep of
hidden changesets sounds useful in other circumstances (the group
extension comes to mind) but I think it will make this change much
bigger than I think it is -- the proposal is really just concerned with
pruning the changesets we consider when pushing.


I'll go look at my slides for my PhD defense now... I just wanted to
toss this idea out here before I leave for Denmark on Sunday. I'll be
the all next week, so I'll probably not be around much on IRC.

-- 
Martin Geisler

aragost Trifork
Professional Mercurial support
http://aragost.com/mercurial/


More information about the Mercurial-devel mailing list