Branches and Heads
Stuart Marks
Stuart.Marks at Sun.COM
Fri Feb 16 03:11:29 UTC 2007
Russell Suter wrote:
> If I create a branch on a branch it appears that there is only
> one head for both branches -- the head is on the second branch.
>
> 10
> |
> +--11 (branch 1)
> |
> +--12 (branch 2) (head) (tip)
>
> If I set back to branch 1, the branch command reports that I'm
> on branch 1 as expected but the revision is revision 12 even if
> I do an update -C. If I update to revision 11 and commit a change
> (creating revision 13) the heads command will show that I have
> two heads:
>
> 10
> |
> +--11--13 (head)(tip)
> |
> +--12 (head)
>
> What I would expect is that revision 11 stays the head of branch 1
> even when branch 2 / revision 12 is created. Also, when I go back
> to branch 1 and update, I get revision 11.
It sounds like you're thinking that 'hg branch' actually creates branches. This
is understandable, since hg's branching doesn't really seem to be described
very well anywhere.
As I understand it, 'hg branch' merely sets or gets the branch name of the
working copy, which is significant only when a commit is done. At that point
the rev created by the commit has a branch label associated with it. This
doesn't affect the topology of the history tree in any way.
Also, 'hg branch' doesn't change the parent rev of the working copy. You have
to do an 'hg update' to do that.
To create a branch explicitly, you need to update the working copy to a
non-head rev and commit a new rev there. This occurs regardless of whether
you've set a branch name with 'hg branch'. If you have, you've created a named
branch; otherwise you've created an unnamed branch.
A "head" is simply a description of where a rev is in the history tree. If a
rev has no children (i.e., it's a leaf node) it's a head, otherwise not. This
is independent of whether it has a branch name.
In your example, I think you did the following:
$ hg parent
changeset: 10:ea198e780bce
tag: tip
...
$ hg branch "branch 1"
$ hg commit # creates rev 11, labeled "branch 1"
$ hg branch "branch 2"
$ hg commit # creates rev 12, labeled "branch 2"
If so, then you're simply adding new revs to the tip. This gives a linear
sequence of revs, with no branches, that happen to have a couple different
branch labels. Since rev 11 is now an interior node in the history tree, it's
not a head.
As you observed you can update back to rev 11 and commit a new rev there, which
truly creates a branch. You can also do 'hg update "branch 1"' which will
update the working copy to the tipmost rev with that branch name, whether or
not that rev happens to be a head.
> To complicate matters, if I do this in a clone of a parent repository,
> when I go to push revision 13, It aborts with the "push creates new
> remote branches!" message.
Right, doing a push that creates a new head is unusual enough that push warns
about it. This is often the case if you did a pull that had a conflict that you
forgot to merge. But if it's truly your intent to create a new head in the
parent, just use push -f.
s'marks
More information about the Mercurial
mailing list