On Wed, Oct 30 2024, Josh Poimboeuf [off-list ref] wrote:
If HEAD isn't associated with an annotated tag, a bug (or feature?) in
"git describe --match" causes it to search every commit in the entire
repository looking for additional match candidates. Instead of it
taking a fraction of a second, it adds 10-15 seconds to the beginning of
every kernel build.
Fix it by adding an additional dummy match which is slightly further
away from the most recent one, along with setting the max candidate
count to 1 (not 2, apparently another bug).
cc += git list
Hm, I tried looking at the git describe source code, and while I can't
claim I understand it very well, I think the main problem is around
this part:
if (!tags && !all && n->prio < 2) {
unannotated_cnt++;
} else if (match_cnt < max_candidates) {
struct possible_tag *t = &all_matches[match_cnt++];
t->name = n;
t->depth = seen_commits - 1;
t->flag_within = 1u << match_cnt;
t->found_order = match_cnt;
c->object.flags |= t->flag_within;
if (n->prio == 2)
annotated_cnt++;
}
else {
gave_up_on = c;
break;
}
So in the case where one doesn't pass any --match, we get something like
git describe --debug 5f78aec0d7e9
describe 5f78aec0d7e9
No exact match on refs or tags, searching to describe
annotated 243 v4.19-rc5
annotated 485 v4.19-rc4
annotated 814 v4.19-rc3
annotated 1124 v4.19-rc2
annotated 1391 v4.19-rc1
annotated 10546 v4.18
annotated 10611 v4.18-rc8
annotated 10819 v4.18-rc7
annotated 11029 v4.18-rc6
annotated 11299 v4.18-rc5
traversed 11400 commits
more than 10 tags found; listed 10 most recent
gave up search at 1e4b044d22517cae7047c99038abb444423243ca
v4.19-rc5-243-g5f78aec0d7e9
and that "gave up" commit is v4.18-rc4, the eleventh commit
encountered. That also explains why you have to add a "dummy" second
--match to make --candidates=1 have the expected behaviour.
Perhaps the logic should instead be that as soon as match_cnt hits
max_candidates (i.e. all the tags we're going to consider have actually
been visited), we break out. That is, the last "else" above should
instead be replaced by
if (match_cnt == max_candidates) {
... /* ? , gave_up_on is now a misnomer */
break;
}
Then as a further DWIM aid, wherever the initialization logic is could
be updated so that, after expanding all the --match= wildcards, if the
number of tags is less than max_candidates, automatically lower
max_candidates to that number (which in the setlocalversion case will
always be 1 because we're not actually passing a wildcard).
Or, we could explicitly on the kernel side pass that --candidates=1, but
yes, I agree it looks like a bug that the loop requires encountering +1
tag to hit that break;.
Rasmus