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