Fossil Forum
Post: Unexpected "recursive" branch rename
Hello forum,
I stumbled upon a quirky behavior involving adding propagating tags to existing check-ins:
I have renamed a feature branch, and the new branch name appeared as an additional tag in named sub-branches. Is the below the intended behavior?
Original
scale = 0.8
fill = white
linewid *= 0.5
circle "C0" fit
circlerad = previous.radius
arrow
circle "C1"
arrow
circle "C2"
arrow
circle "C5"
arrow
circle "C6"
circle "C3" at dist(C2,C5) heading 30 from C1
arrow
circle "C4"
arrow invisible
circle "C7"
arrow from C5 to C7 chop
arrow from C1 to C3 chop
arrow from C4 to C5 chop
arrow from C5 to C7 chop
box height C3.y-C2.y \
width (C6.e.x-C0.w.x)+1.5*C1.radius \
with .w at 0.5*linewid west of C0.w \
behind C0 \
fill 0xc6e2ff thin color gray
box same width 1.3*(C4.e.x - C3.w.x) \
with .s at previous.n \
fill 0x9accfc
box same width 0.8*(C4.e.x - C3.w.x) \
with .sw at previous.se \
fill red
"feature_branch_with_typo" below at 3rd last box.s
"sub-feature_branch" above at 2nd last box.n
"bogus" above at last box.n
Editing the first check-in (C0) of branch feature_branch_with_typo and renaming the branch (Using "Starting from this check-in, rename the branch to") resulted in both the actual branch and all descendants to inherit the new tag, like this:
scale = 0.8
fill = white
linewid *= 0.5
circle "C0" fit
circlerad = previous.radius
arrow
circle "C1"
arrow
circle "C2"
arrow
circle "C5"
arrow
circle "C6"
circle "C3" at dist(C2,C5) heading 30 from C1
arrow
circle "C4"
arrow invisible
circle "C7"
arrow from C5 to C7 chop
arrow from C1 to C3 chop
arrow from C4 to C5 chop
arrow from C5 to C7 chop
box height C3.y-C2.y \
width (C6.e.x-C0.w.x)+1.5*C1.radius \
with .w at 0.5*linewid west of C0.w \
behind C0 \
fill 0xc6e2ff thin color gray
box same width 1.3*(C4.e.x - C3.w.x) \
with .s at previous.n \
fill 0x9accfc
box same width 0.8*(C4.e.x - C3.w.x) \
with .sw at previous.se \
fill red
"typo_corrected" below at 3rd last box.s
"sub-feature_branch | typo_corrected" above at 2nd last box.nw
"bogus | typo_corrected" above at last box.ne
My expectation was that only the descendants on the same branch name get the new branch name, and descendants with a different name are untouched, like this:
scale = 0.8
fill = white
linewid *= 0.5
circle "C0" fit
circlerad = previous.radius
arrow
circle "C1"
arrow
circle "C2"
arrow
circle "C5"
arrow
circle "C6"
circle "C3" at dist(C2,C5) heading 30 from C1
arrow
circle "C4"
arrow invisible
circle "C7"
arrow from C5 to C7 chop
arrow from C1 to C3 chop
arrow from C4 to C5 chop
arrow from C5 to C7 chop
box height C3.y-C2.y \
width (C6.e.x-C0.w.x)+1.5*C1.radius \
with .w at 0.5*linewid west of C0.w \
behind C0 \
fill 0xc6e2ff thin color gray
box same width 1.3*(C4.e.x - C3.w.x) \
with .s at previous.n \
fill 0x9accfc
box same width 0.8*(C4.e.x - C3.w.x) \
with .sw at previous.se \
fill red
"typo_corrected" below at 3rd last box.s
"sub-feature_branch" above at 2nd last box.n
"bogus" above at last box.n
I resolved this by manually cancelling the new branch name on all sub-branches.
The current behavior would mean that renaming trunk at the "first, empty check-in" to e.g. main would attach that name to every check-in in the repository, regardless of the original branch.
Used fossil was
This is fossil version 2.26 [611144ddd9] 2025-05-16 13:52:48 UTC
Greetings,
Thomas
Editing the first check-in (C0) of branch feature_branch_with_typo and renaming the branch (Using "Starting from this check-in, rename the branch to") resulted in both the actual branch and all descendants to inherit the new tag
new tag? What new tag? I am wondering if you have the same misconception that I started out with on first reading of Branching, Forking, Merging, and Tagging
I am also wondering: * what command did you use to name the branch beginning C3? Typically you would have said commit -new-branch sub-feature_branch * what command(s) did you use to rename the branch at C0? I would expect amend --branch typo_corrected C0 * does 'bogus' represent another branch, or just a fork? If the latter it should acquire the corrected branch name by propagation from its parent C5.
On my first read of the 'branching' document I made the mistake of thinking a branch X would be represented with a propagating tag X. I missed the idea that tags come in two flavours - either just a name, or a name with a value. A branch tag is a tag with name 'branch' and value 'branch name'. So branch X starts with a tag branch=X.
You must have done something other than the suggestion above: there is no new tag on C0, you are just changing branch=feature_typo to branch=feature. This does not propagate to C3 because that has an explicit branch=sub_feature. It may or may not propagate to 'bogus' depending on whether you intend that to be a branch or just a fork.
If you are still stuck try fossil tag list on each checkin.
Aside: I am assuming C0 is the beginning of the branch you are trying to rename. If it isn't you are likely to confuse things because you are not really renaming the branch, but making it into two. A branch has no real identity in itself, its just a name.
Thanks for chiming in.
I am assuming C0 is the beginning of the branch you are trying to rename.
Yes it is. C0 is a branch started from trunk by fossil commit --branch feature_branch_with_typo
what command did you use to name the branch beginning C3? Typically you would have said commit -new-branch sub-feature_branch
While on feature_branch_with_typo, I used fossil commit --branch sub-feature_branch
what command(s) did you use to rename the branch at C0?
/ci_edit on the web interface, specifically the quoted option "Starting from this check-in, rename the branch to: [ ]"
new tag?
"new tag" meant the branch name tag typo_corrected assigned via the web UI
does 'bogus' represent another branch?
Yes, one with two faulty check-ins I manually moved from feature_branch_with_typo via the web UI
The exact aftermath can be observed in the timeline here. You can see two "Cancel tag" artifacts in the timeline, that revert the unwanted parts of the previous "Move to branch" artifact
Thank you for that.
I've learned / remembered something else about branches and tags: a branch X isn't just branch=X, there is also a sym-X, for some subtle reason. I only say 'subtle' because I can't think what it might be. Knowing the Fossil folk I am sure there will be one.
Do you recall what it was you saw that told you the new 'weight' tag was visible? It should not matter, because it does not by itself define which branch you are on - without a matching branch=X, sym-X is just a tag. A check-in can never be on more than one branch, because there can only be one branch tag.
To check my thinking:
C0 seems to be fd21, C2 c307 (with a few more in between) C3 2392, C5 7415. There doesn't seem to be any C4, but I don't think that matters.
The 'typo' seems to be changing 'score' to 'weights'.
This looks to me like it should, other than your two 'cancel' operations.
Unfortunately unless I have missed something the UI doesn't tell us the difference between: * Adding a new branch=X, and replacing an existing branch=Y with branch=X (which is what a rename does) * Cancelling a tag X (sym-X) which existed, and adding a cancel to block inheritance from a parent (when you started a new branch with C3 'score' had to be blocked)
I am assuming this isn't hiding anything relevant.
Maybe this gives us the reason for the sym tag: I am guessing that the sym tag is needed to support queries like 'find me all the checkins for branch X'. But you can't use just a sym tag to identify a branch because of the type of scenario you have - in order to rename a branch you would have to find all the sub branches and adjust the cancel tags.
Instead you change the query to return only those nodes which also have branch=X. In other words, it is easier to find all the nodes with tags named sym-X and then check ancestor-or-self for branch=X than it is to find all the nodes with tags named branch, and then filter those on the value branch=X.
Perhaps someone more knowledgable than either of us will chip in - but meanwhile I think you can ignore the extra tags if it happens again: it is just an implementation detail.