Skip to content

Commit f9b8908

Browse files
derrickstoleegitster
authored andcommitted
commit: use generation numbers for in_merge_bases()
The containment algorithm for 'git branch --contains' is different from that for 'git tag --contains' in that it uses is_descendant_of() instead of contains_tag_algo(). The expensive portion of the branch algorithm is computing merge bases. When a commit-graph file exists with generation numbers computed, we can avoid this merge-base calculation when the target commit has a larger generation number than the initial commits. Performance tests were run on a copy of the Linux repository where HEAD is contained in v4.13 but no earlier tag. Also, all tags were copied to branches and 'git branch --contains' was tested: Before: 60.0s After: 0.4s Rel %: -99.3% Reported-by: Jeff King <[email protected]> Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 819807b commit f9b8908

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

commit.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1056,12 +1056,19 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit *
10561056
{
10571057
struct commit_list *bases;
10581058
int ret = 0, i;
1059+
uint32_t min_generation = GENERATION_NUMBER_INFINITY;
10591060

10601061
if (parse_commit(commit))
10611062
return ret;
1062-
for (i = 0; i < nr_reference; i++)
1063+
for (i = 0; i < nr_reference; i++) {
10631064
if (parse_commit(reference[i]))
10641065
return ret;
1066+
if (reference[i]->generation < min_generation)
1067+
min_generation = reference[i]->generation;
1068+
}
1069+
1070+
if (commit->generation > min_generation)
1071+
return ret;
10651072

10661073
bases = paint_down_to_common(commit, nr_reference, reference);
10671074
if (commit->object.flags & PARENT2)

0 commit comments

Comments
 (0)