Fossil User Forum

RFC/RFE: improving branch color collisions
Login

RFC/RFE: improving branch color collisions

RFC/RFE: improving branch color collisions

(1) By Stephan Beal (stephan) on 2025-09-24 16:46:37 [link] [source]

Based on a /chat discussion with Martin Gagnon:

The automatic branch colors are sometimes so close that they're difficult to distinguish. A timely example of this can be seen at:

https://sqlite.org/src/timeline?c=85fe9c6155f72583&skin=eagle&once

Ideas on how to improve upon that are failing me, given how the timeline is rendered: we don't(?) know all of the colors in advance, AFAIK, so cannot(?) filter/modify that list before rendering the timeline. If we knew all relevant colors in advance, we could go through them and tweak any which are "too close".

Maybe we can keep track of them incrementally and adjust the next color appropriately if there's too close of a match in the list of already-seen colors.

We can't retroactively change the colors as collisions are encountered because by the time one is encountered, older HTML elements have already been emitted.

What if...

(Just spitballing...)

Instead of adding bgcolor attributes to the affected elements, we instead add a CSS class to each named branch-color-NNN, where NNN is a number in the range (say) 1..20. The timeline view could keep track of how many branches it's rendered so far and always assign the Nth branch-color-NNN CSS class to the Nth branch. When we have more than (say) 20 branches, it loops around the color chart and starts anew.

We could pre-define those (say) 20 colors in CSS for both light- and dark-themed skins.

This would guaranty no collisions so long as there are fewer than (say) 20 branches shown at once, and would reduce collisions to 1/20th when many branches are shown.

The down-side would be that the colors of each branch could change on each visit, which may cause some confusion.

Other ideas for how to improve this would be welcomed.

(2.1) By Jörgen Kosche (jkosche) on 2025-09-24 19:03:49 edited from 2.0 in reply to 1 [link] [source]

I like that the chosen color is stable for a given branch. Maybe something else could be done.

Gradient

I don't know, looks a bit crazy. Maybe it can be tweaked. This is:

style="background:linear-gradient(0deg, #edc9f1, #f8f6cf)"

Maybe it can be tweaked to look better? I dunno.

But the advantage would be: as two colors are chosen from the hash (which should be possible), the number of combinations is the square of the current number of choices. Which should make collisions quite a bit more unlikely.

linear-gradient() was rolled out in CSS of browsers in 2012 and 2013, only Edge got it only 2015. I think that is around long enough that most users should have browser-support.

Just an idea.

...

I assume char *hash_color(const char *z) in color.c calculates the color?


EDIT: The radial-gradient() and the repeating variants to both were introduced at the same time:

repeating gradient

style="background:repeating-linear-gradient(to right, #cbf0e8 0, #f2ceca 10px, #cbf0e8 20px)"

(3.2) By Andy Bradford (andybradford) on 2025-09-25 03:21:19 edited from 3.1 in reply to 1 [link] [source]

Just for fun, I decided to revert the changes introduced here:

https://fossil-scm.org/home/info/fb3dabd5c4

The contrast is better, I think, but  then for lighter skins it may have
more difficulty (the original reason for the change in [fb3dabd5c4]).

Here's what it looks like with the change reverted:

http://fossil.bradfords.org:11072/sqlite/timeline?advm=0&c=85fe9c6155f72583&n=50&once=&skin=eagle&ss=x&udc=1&y=ci

Not sure which is better (with or without [fb3dabd5c4]).

Andy

(7) By Stephan Beal (stephan) on 2025-09-25 13:21:41 in reply to 3.2 [source]

Just for fun, I decided to revert the changes introduced here: ...

Just for context: those changes were made in cooperation with a color-blind project member (the late Scott Robison).

Here's what it looks like with the change reverted:

i like it :).

Not sure which is better

For you and i, probably the rolled-back one. i have no clue what our number of color-blind users is nor how drastic that change is (depending on their specific type of color-blindness), so won't advocate for one or the other (and will be content with whichever approach y'all come up with).

BTW: after having thought about it more yesterday i agree with all of you that "cyclic" colors (as Florian put it so well) would be really irritating.

(What if the hash colors were based on the checkin time instead of their name? Would that generate fewer or more collisions?)

(8) By Andy Bradford (andybradford) on 2025-09-27 01:51:53 in reply to 7 [link] [source]

> (What if  the hash colors  were based on  the checkin time  instead of
> their name? Would that generate fewer or more collisions?)

I decided to  experiment to see what this would  look like using changes
that I introduced here:

https://fossil-scm.org/home/info/1851b26d2b7894f5

Then I built it and put it up for comparison.

Here is the current color hashing in action using [82888a0d35] (trunk):

S1) http://fossil.bradfords.org:8181/sqlite/timeline?advm=0&c=85fe9c6155f72583&n=50&ss=x&once&skin=eagle


Here are the changes I introduced in [1851b26d2b]:

S2) http://fossil.bradfords.org:8282/sqlite/timeline?advm=0&c=85fe9c6155f72583&n=50&ss=x&once&skin=eagle


And here  are the changes  in [1851b26d2b] with  [fb3dabd5c4] "reverted"
(uncommitted):

S3) http://fossil.bradfords.org:8383/sqlite/timeline?advm=0&c=85fe9c6155f72583&n=50&ss=x&once&skin=eagle


Remove the &once&skin=eagle from the URL  to see what it looks like with
the default skin.

And for the sake of comparison,  let's see what the Tcl repository looks
like since it seems to always have dozens of active branches:

T1) http://fossil.bradfords.org:8181/tcl/timeline?once&skin=eagle

T2) http://fossil.bradfords.org:8282/tcl/timeline?once&skin=eagle

T3) http://fossil.bradfords.org:8383/tcl/timeline?once&skin=eagle


Given the above  examples, it does seem to me  that using the datetime()
as the  input for the  color hashing does  generally result in  a better
distribution of colors than using the branch name.

I  imagine that  there will  always  be some  combination of  datetime()
inputs on  branches that don't mix  well. In fact, if  you look closely,
you'll notice that there isn't much difference between the "mistake" and
"short-circuit" branches when using S1 and S2, however, when viewed with
S3 there is considerable difference. I  could see S3/T3 being the winner
here,  even  though it  would  remove  whatever  benefit was  gained  in
[fb3dabd5c4], however,  given these  few examples,  it looks  like S2/T2
might be better than S1/T1.

Maybe we should consider a different approach altogether?

Thoughts?

Andy

(9) By Andy Bradford (andybradford) on 2025-09-27 02:30:52 in reply to 8 [link] [source]

> Given the above examples, it does seem to me that using the datetime()
> as the input  for the color hashing does generally  result in a better
> distribution of colors than using the branch name.

Also, be sure  to scroll from top  to bottom on some  of these examples,
as  you'll  see other  branches  with  differences  in colors  that  are
interesting.

(10) By Florian Balmer (florian.balmer) on 2025-09-27 04:20:31 in reply to 8 [link] [source]

Not sure if this will help a lot. Sometimes the colors for similar branch names, say version-1 and version-2, look almost identical, and sometimes they look completely different. I'm not sure if basing the color generation on date/time stamps will really produce more variability.

(11) By Florian Balmer (florian.balmer) on 2025-09-27 04:26:22 in reply to 10 [link] [source]

I think the color space is intentionally limited to restrict variability, probably based on feedback by color-blind users, as mentioned by Stephan.

(14) By Andy Bradford (andybradford) on 2025-09-27 13:41:08 in reply to 11 [link] [source]

> I think the color space is intentionally limited to restrict variability

And that's fine.  I'm fine either way. The lighter  colors (when using a
light skin) actually are somewhat  nicer for readability than the darker
original hashed colors.

Andy

(17) By Florian Balmer (florian.balmer) on 2025-09-27 16:02:04 in reply to 14 [link] [source]

BTW: For users concerned about readability:

Despite some recent enhancements for the default skin, most of the light-mode skins don't use black text color, and most of the dark-mode skins don't use white text color. Changing the skin to display text in black or white instead of grayish improves readability, especially for areas with another background color.

(18) By Florian Balmer (florian.balmer) on 2025-09-27 16:55:47 in reply to 14 [link] [source]

Thoughts:

I'm often "transplanting" (partial) branches across repositories, would they have different colors (even for the same branch name) on each repository if the commit time by the script is different?

What about reusing merged and closed branch names, would each reused branch section look different?

Yes/yes gets a -1/-1 vote from me, I think.

(19) By Florian Balmer (florian.balmer) on 2025-09-27 17:13:17 in reply to 18 [link] [source]

Hm, indeed looks like a -1/-1 from me.

I prefer "moved" and reopened branches to have the same colors.

(20) By Andy Bradford (andybradford) on 2025-09-27 21:03:36 in reply to 18 [link] [source]

> I'm  often  "transplanting"  (partial) branches  across  repositories,
> would they have different colors

If by this you mean that you  use the exact same branch name on multiple
different  repositories with  the expectation  that they  have the  same
color in  the timeline, this  clearly won't  happen with the  color hash
based upon the timestamp of the start of the branch.

> What about reusing merged and closed branch names

Even within the same repository  they might not---that might actually be
arguably  a  nice feature  because  there  really isn't  a  relationship
between those branches other than the name.

Here's a  view of all the  "mistake" branches in the  Fossil repository,
for example:

http://fossil.bradfords.org:8282/fossil/timeline?r=mistake

I can see an argument to be made that this is actually decent behavior.

However, that  being said,  if the  expectation is  that a  given branch
"name" is supposed  to have the same color across  multiple and distinct
repositories, then clearly the experiment to generate the color hash off
of the start of the branch  timestamp is not desirable. I personally had
never actually  thought that my branches,  if given the same name, would
have the same automatically assigned color.  I can see, however, that it
certainly could be useful to those who expect it.

What's  the best  behavior  here? Current  behavior?  Old behavior?  New
behavior using timestamp?  A combination?

I hesitate  to ask, but should  it be a configurable  option? :-) Branch
color  behavior is  such a  subjective  thing that  it's going  to be  a
challenge to reach consensus.

I   only  presented   these   changes  because   Stephan  wondered   how
timestamp-based hash would look. We can  abandon the changes if it's not
really  an  improvement and  perhaps  think  about  the problem  from  a
different perspective.

Perhaps improving the way the name-based hash is generated.

Andy

(21) By Stephan Beal (stephan) on 2025-09-27 23:45:11 in reply to 20 [link] [source]

What's the best behavior here? Current behavior? Old behavior? New behavior using timestamp? A combination?

FWIW, i like/prefer what you've done but...

Branch color behavior is such a subjective thing that it's going to be a challenge to reach consensus.

... also have no strong preference. It's one of those things which goes unnoticed until there's a color collision, then the collision eventually passes as branches come and go, so no real harm done.

Y'all work it out and i'll be happy with what i get :).

(22) By Florian Balmer (florian.balmer) on 2025-09-28 03:42:22 in reply to 20 [link] [source]

Consider a more long-running branch that was reused:

http://fossil.bradfords.org:8282/fossil/timeline?r=js-hamburger-menu

This is the definitive show-stopper for me, and I prefer to stick with the current behavior. And yes, I really want branches with the same name look the same across various repositories.

But note that I can easily patch this for my private version of Fossil if you need something fresh (and confusing) to look at! ;-)

(28) By Andy Bradford (andybradford) on 2025-09-30 06:08:00 in reply to 22 [link] [source]

> And  yes, I  really want  branches with  the same  name look  the same
> across various repositories.

That's the  real challenge...  avoiding collisions while  also retaining
the ability  to have the same  branch name use the  same automatic color
across repositories.

What about using MD5 to generate the color hashes?

https://fossil-scm.org/home/info/d4caf785e39715ba

Your reused branch name:

http://fossil.bradfords.org:8484/fossil/timeline?r=js-hamburger-menu

The original problematic  URL (notice that the mistake branch  now has a
nice unique color):

http://fossil.bradfords.org:8484/sqlite/timeline?c=85fe9c6155f72583&skin=eagle&once

Branch list with colors:

http://fossil.bradfords.org:8484/fossil/brlist?udc=1&colors=on

Tcl and it's plethora of branches:

http://fossil.bradfords.org:8484/tcl/timeline


Some questions that I had with this approach to use MD5.

1) Will the use of MD5 be too expensive?

I didn't see any noticeable difference  in the speed of rendering pages,
but in aggregate  there may be something to consider.  Or maybe it won't
be but a blip.


2) Is there  a better mechanism for preserving the  random nature of the
MD5 hash than reducing it the way I did?

I think  the results are fairly  decent, however, I do  notice that when
looking at the Tcl timeline there  are more near collisions than I would
like. Is that perhaps  due to the way I reduced the 16  byte MD5 hash to
an unsigned int?

Comments?

Andy

(29) By Florian Balmer (florian.balmer) on 2025-09-30 06:36:48 in reply to 28 [link] [source]

I think the magic is in reasonable_bg_color(), which limits the available color space, maybe just for light/dark, maybe also for color blindness. No matter how "random" the input hash is.

Enabling raw-bgcolor may give more variation, but also less readabaility.

BTW: I think the Tcl/Tk folks use a lot of explicit colors for their branches.

(30) By Florian Balmer (florian.balmer) on 2025-09-30 06:41:05 in reply to 29 [link] [source]

And here.

(31) By Martin Gagnon (mgagnon) on 2025-09-30 11:18:50 in reply to 28 [link] [source]

What about using MD5 to generate the color hashes?

This would definitively help for the names like "something_v1" / "something_v2" generated branch color that are indistinguishable.

(32) By Florian Balmer (florian.balmer) on 2025-09-30 13:38:05 in reply to 31 [link] [source]

No, it wouldn't.

It's not a problem of "randomness", i.e. similar branch names can be assigned very similar or very different branch colors, see this example:

It's a problem of the narrowed color space, due to background-foreground and probably color blindness requirements.

(33) By Florian Balmer (florian.balmer) on 2025-09-30 13:51:36 in reply to 32 [link] [source]

(36) By Florian Balmer (florian.balmer) on 2025-09-30 15:05:34 in reply to 33 [link] [source]

(37) By Andy Bradford (andybradford) on 2025-09-30 15:13:11 in reply to 36 [link] [source]

> This one has also quite a few potential conflicts:

Yep, I plan to address later today.

(38.1) By Andy Bradford (andybradford) on 2025-10-01 06:07:12 edited from 38.0 in reply to 36 [link] [source]

> Maybe even more than with the current approach:

The trouble is one can only  take hashing so far given the modifications
that are then  being done with the  hash data and also  the smoothing of
the colors. Is there anything more that can be eeked out of hashing?

I've pushed my latest changes and published here:

http://fossil.bradfords.org:8585/fossil/hash-color-test?b0=another-thing-v0&b1=another-thing-v1&b2=another-thing-v2&b3=another-thing-v3&b4=another-thing-v4&b5=another-thing-v5&b6=another-thing-v6&b7=another-thing-v7&b8=another-thing-v8&b9=another-thing-v9

http://fossil.bradfords.org:8585/fossil/hash-color-test?b0=something_v0&b1=something_v1&b2=something_v2&b3=something_v3&b4=something_v4&b5=something_v5&b6=something_v6&b7=something_v7&b8=something_v8&b9=something_v9

http://fossil.bradfords.org:8585/fossil/brlist?udc=1&colors=on

And the originally reported timeline view:

http://fossil.bradfords.org:8585/sqlite/timeline?advm=0&c=85fe9c6155f72583&n=50&once=&skin=eagle&ss=x

By the way, thanks for pointing  me to the /hash-color-test page. I knew
of the  command line test-hash-color  subcommand, but didn't  know about
the page---that was helpful.

Thanks,

Andy

(39) By Andy Bradford (andybradford) on 2025-10-02 03:39:27 in reply to 38.1 [link] [source]

> Is there anything more that can be eeked out of hashing?

Yes, I found a bug in the way I was calculating the hash and replaced it
with something a  little more "standard". I rebuilt  and published again
on the previous URLs on port 8585 and I think they look pretty good from
my perspective.

Andy

(40) By Florian Balmer (florian.balmer) on 2025-10-02 12:10:29 in reply to 39 [link] [source]

My opinion tends to go back to Post 32.

Here's a visual map of the branch colors from five different versions of Fossil with five different methods to generate branch colors.

The first block is sorted by branch modification time and illustrates color collisions. The second block is sorted by color and illustrates color distribution.

So maybe randomization is not the problem, after all?

(41) By Florian Balmer (florian.balmer) on 2025-10-02 12:13:07 in reply to 40 [link] [source]

So maybe randomization is not the problem, after all ...

But the fact that there's effectively only about 8 distinct colors?

(34) By Martin Gagnon (mgagnon) on 2025-09-30 13:52:27 in reply to 32 [link] [source]

May be, but at the end it happens *v1 and *v2 always have this problem and having a way to override the color easily and at the same time having it to work with dark and light theme would be useful.

I don’t know what would be the best way to do that, but now the only way to override is to force a manual color which can become unusable on different theme.

Perhaps we could have the manually selected color to pass through this kind of process ?

(35) By Florian Balmer (florian.balmer) on 2025-09-30 13:54:31 in reply to 34 [link] [source]

See reply 33.

(23) By Martin Gagnon (mgagnon) on 2025-09-28 12:58:04 in reply to 20 [link] [source]

I think, what we need is just a way to override a color when needed (collision or just because one don't like the generated color).

Pehaps we could keep original behavior (based on the branch name), but we could have an option to override with an alternate input string just for the color generation.

  • Were we edit the checkin, we have option to override the color like now, but it could be a button that generate a random string, the user could press this button until he is happy with the color.
    • So now the color we override can work with different theme.

I think this is very useful.. with timestamp, color collision can still happens we may still want to override the color.

(24) By Florian Balmer (florian.balmer) on 2025-09-28 15:22:53 in reply to 23 [link] [source]

We already have:

  • fossil ci--branchcolor
  • fossil amend--branchcolor
  • /ci_editnewclr

Putting a "random string" somewhere (where? would it sync? etc.) just for color generation seems whacky.

A minimally invasive solution might be that the /ci_edit web UI provides facilities to generate a random branch (or check-in, i.e. propagating or non-propagating) color that simply changes the bgcolor special tag, as it already does if a color is set manually. But this still feels like overengineering, if the user is already in the /ci_edit page, they can just pick any color they like, themselves.

(25) By Florian Balmer (florian.balmer) on 2025-09-28 15:43:27 in reply to 24 [link] [source]

(26) By ravbc on 2025-09-29 11:00:38 in reply to 24 [link] [source]

Putting a "random string" somewhere (where? would it sync? etc.) just for color generation seems whacky.

It is overengineering for sure, but using some tag as a addendum to branch name for color choosing will allow simple changing of conflicting colors for similarly named branches with one mouse click (if a button for setting it will be available somewhere).

(27) By Florian Balmer (florian.balmer) on 2025-09-30 04:54:03 in reply to 26 [link] [source]

Introducing a new special tag brings quite some overhead: it has to be explicitly ignored in many places so as not to show up as an ordinary tag, and many UI and CLI commands need new facilities to use or modify it.

Note that with the recent changes to background color handling linked in a previous post, you can do:

fossil amend start:"BRANCHNAME" --branchcolor="orange"

Fossil will now translate "orange" to a numeric form and auto-adjust it for light and dark themes.

Also see the Background Color Test page.

(12) By Florian Balmer (florian.balmer) on 2025-09-27 04:44:32 in reply to 8 [link] [source]

BTW: the /brlist?colors=on page provides a good overview of branch colors and readability (not yet updated in your examples).

(16) By Andy Bradford (andybradford) on 2025-09-27 13:46:09 in reply to 12 [link] [source]

> BTW:  the /brlist?colors=on  page provides a  good overview  of branch
> colors and readability

Yes, I had forgotten about that page, I'll take a look, thanks.

Andy

(13) By Stephan Beal (stephan) on 2025-09-27 06:43:33 in reply to 8 [link] [source]

Here are the changes I introduced in...

My eyes thank you!

The one(?) down-side is that we're using the timestamp of the most recent checkin, so each branch's colors may change at any moment. What if, instead, we use the timestamp of the start of the branch using the special name "start:branchname"?

:-?

(15) By Andy Bradford (andybradford) on 2025-09-27 13:44:35 in reply to 13 [link] [source]

> What if,  instead, we  use the  timestamp of the  start of  the branch
> using the special name "start:branchname"?

It should already be using the timestamp  of the start of the branch; at
least  that was  my  original intent  with  using the  start_of_branch()
method:

https://fossil-scm.org/home/artifact?udc=1&ln=278&name=74a5ee6168245720

Andy

(4) By Florian Balmer (florian.balmer) on 2025-09-25 05:26:46 in reply to 1 [link] [source]

Yes, I also prefer stable colors.

My ftime CLI script does "cyclic" color allocation, and I don't like it. I expect this to be even more irritating with web UI background colors.

My patched version of Fossil does "whitewashing" of colors (for light-mode skins). This looked great with the "old" algorithm pointed out by Andy and had more diverse colors than the "new" (current) one.

(5) By Florian Balmer (florian.balmer) on 2025-09-25 05:32:52 in reply to 4 [link] [source]

PS: The transparent SVG backgrounds to mix in white (or black, for dark-mode skins) correspond to alpha-blending and could also be calculated directly on the "old" algorithm instead of being applied through SVG backgrounds.

(6) By Florian Balmer (florian.balmer) on 2025-09-25 08:09:36 in reply to 5 [link] [source]

PPS: Overall, I think the branch coloring system is pretty decent with the latest recent changes from drh, and if branch color collision is a real problem, it's easy to assign a user-defined color to some long-running branch, for example.