diff options
| author | Derrick Stolee <stolee@gmail.com> | 2026-04-06 13:27:28 +0000 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2026-04-06 12:02:30 -0700 |
| commit | b0ba57daa86dfba0a6551613452d1cb2301266a2 (patch) | |
| tree | 9df6b16773cf2b259fc8426c5814db52a59fe34a /contrib/persistent-https | |
| parent | e8e5453ab8794cf29afe0a616d74319442b676bd (diff) | |
| download | git-b0ba57daa86dfba0a6551613452d1cb2301266a2.tar.gz git-b0ba57daa86dfba0a6551613452d1cb2301266a2.zip | |
rev-list: use reduce_heads() for --maximal-only
The 'git rev-list --maximal-only' option filters the output to only
independent commits. A commit is independent if it is not reachable from
other listed commits. Currently this is implemented by doing a full
revision walk and marking parents with CHILD_VISITED to skip non-maximal
commits.
The 'git merge-base --independent' command computes the same result
using reduce_heads(), which uses the more efficient remove_redundant()
algorithm. This is significantly faster because it avoids walking the
entire commit graph.
Add a fast path in rev-list that detects when --maximal-only is the only
interesting option and all input commits are positive (no revision
ranges). In this case, use reduce_heads() directly instead of doing a
full revision walk.
In order to preserve the rest of the output filtering, this computation
is done opportunistically in a new prepare_maximal_independent() method
when possible. If successful, it populates revs->commits with the list
of independent commits and set revs->no_walk to prevent any other walk
from occurring. This allows us to have any custom output be handled
using the existing output code hidden inside
traverse_commit_list_filtered(). A new test is added to demonstrate that
this output is preserved.
The fast path is only used when no other flags complicate the walk or
output format: no UNINTERESTING commits, no limiting options (max-count,
age filters, path filters, grep filters), no output formatting beyond
plain OIDs, and no object listing flags.
Running the p6011 performance test for my copy of git.git, I see the
following improvement with this change:
Test HEAD~1 HEAD
------------------------------------------------------------
6011.2: merge-base --independent 0.03 0.03 +0.0%
6011.3: rev-list --maximal-only 0.06 0.03 -50.0%
6011.4: rev-list --maximal-only --since 0.06 0.06 +0.0%
And for a fresh clone of the Linux kernel repository, I see:
Test HEAD~1 HEAD
------------------------------------------------------------
6011.2: merge-base --independent 0.00 0.00 =
6011.3: rev-list --maximal-only 0.70 0.00 -100.0%
6011.4: rev-list --maximal-only --since 0.70 0.70 +0.0%
In both cases, the performance is indeed matching the behavior of 'git
merge-base --independent', as expected.
Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'contrib/persistent-https')
0 files changed, 0 insertions, 0 deletions
