Branches and Heads
Russell Suter
maverick at simlogix.com
Mon Feb 19 16:21:00 UTC 2007
Stuart Marks wrote:
> 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
Thanks Stuart! The 'hg update <branch name>' did the trick. It behaves
exactly as I expected.
Regards,
--
Russ
More information about the Mercurial
mailing list