atom feed69 messages in com.selenic.mercurial-develRFC: dealing with dead, anonymous fea...
FromSent OnAttachments
Martin GeislerMay 7, 2010 10:34 am 
Dirkjan OchtmanMay 7, 2010 10:37 am 
Matt MackallMay 7, 2010 11:00 am 
Martin GeislerMay 7, 2010 11:14 am 
Matt MackallMay 7, 2010 11:46 am 
Dirkjan OchtmanMay 7, 2010 1:14 pm 
Gilles MorisMay 8, 2010 12:10 am 
Martin GeislerMay 8, 2010 1:31 am 
Martin GeislerMay 8, 2010 1:34 am 
Martin GeislerMay 8, 2010 1:48 am 
Martin GeislerMay 8, 2010 2:09 am 
Gilles MorisMay 8, 2010 3:50 am 
Martin GeislerMay 8, 2010 1:10 pm 
Gilles MorisMay 9, 2010 9:33 am 
Gilles MorisMay 9, 2010 1:50 pm 
Gilles MorisMay 9, 2010 1:50 pm 
Gilles MorisMay 9, 2010 1:50 pm 
Gilles MorisMay 9, 2010 1:50 pm 
Gilles MorisMay 9, 2010 1:50 pm 
Matt MackallMay 9, 2010 2:37 pm 
Matt MackallMay 9, 2010 2:44 pm 
Matt MackallMay 9, 2010 2:46 pm 
Matt MackallMay 9, 2010 2:47 pm 
Martin GeislerMay 9, 2010 4:12 pm 
Dirkjan OchtmanMay 9, 2010 10:50 pm 
Gilles MorisMay 9, 2010 11:31 pm 
43 later messages
Subject:RFC: dealing with dead, anonymous feature branches
From:Martin Geisler (
Date:May 7, 2010 10:34:11 am

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]


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.

aragost Trifork Professional Mercurial support