Re: Bug report - git rev-list --exclude-first-parent-only [SEC=UNOFFICIAL]
Jerry Zhang <[email protected]>
| Newsgroups | org.kernel.vger.git |
|---|---|
| Message-ID | <CAMKO5Cu0i3UKT61th3ZUiiQTkPa+YtxGQAQSXJjNWGWaTs8OGg@mail.gmail.com> |
On Fri, Jul 3, 2026 at 1:28 PM Junio C Hamano <[email protected]> wrote: > > Michael Hore <[email protected]> writes: > > > I believe I have found a bug - > > > > My repo has a commit structure like > > > > R2 > > |\ > > | F > > |/ > > R1 > > > > i.e. > > - there is a merge commit R2 with parents R1 and F > > - the parent of F is R1 > > IOW, R2 is a useless merge that could have been a simple > fast-forward directly to F. > > > I ran "git rev-list --exclude-first-parent-only F ^R2" > > > > it gave the expected result: "F" > > > > I ran "git rev-list --exclude-first-parent-only F R1 ^R2" > > > > I expected the same result, but I got an unexpected result - nothing at all > > This seems to have come from 9d505b7b49 (git-rev-list: add > --exclude-first-parent-only flag, 2022-01-11). I do not know if the > original author is still around, but it would have been nicer to ask > for input from them (cc'ed). > > A fix could be something along this line, but I've never used this > feature even once (I instead use Michael Haggerty's exellent "git > when-merged" thing), so I may very well be breaking _other_ use > cases this feature was originally intended for without knowing. fwiw when-merged seems to be asking the question "when was X branch merged into the baseline", while exclude-first-parent-only is asking "when did X branch first split off from the baseline". of course that property may not be interesting to you if you're looking for the former. > > The patched part is inside a huge "while (parent)" loop. The idea > is to break out before the loop goes on to smudge later parents when > we are in the "smudge only first parent as uninteresting, without > contaminating the history leading to other parents" mode. > > revision.c | 10 ++++++++-- > t/t6012-rev-list-simplify.sh | 18 ++++++++++++++++++ > 2 files changed, 26 insertions(+), 2 deletions(-) > > diff --git c/revision.c w/revision.c > index e91d7e1f11..1f50d42a7a 100644 > --- c/revision.c > +++ w/revision.c > @@ -1151,12 +1151,18 @@ static int process_parents(struct rev_info *revs, struct commit *commit, > if (p) > p->object.flags |= UNINTERESTING | > CHILD_VISITED; > - if (repo_parse_commit_gently(revs->repo, p, 1) < 0) > + if (repo_parse_commit_gently(revs->repo, p, 1) < 0) { > + if (revs->exclude_first_parent_only) > + break; > continue; > + } > if (p->parents) > mark_parents_uninteresting(revs, p); > - if (p->object.flags & SEEN) > + if (p->object.flags & SEEN) { > + if (revs->exclude_first_parent_only) > + break; > continue; > + } > p->object.flags |= (SEEN | NOT_USER_GIVEN); > if (queue) > prio_queue_put(queue, p); > diff --git c/t/t6012-rev-list-simplify.sh w/t/t6012-rev-list-simplify.sh > index 4cecb6224c..2284bbba12 100755 > --- c/t/t6012-rev-list-simplify.sh > +++ w/t/t6012-rev-list-simplify.sh > @@ -285,4 +285,22 @@ test_expect_success 'log --graph --simplify-merges --show-pulls' ' > test_cmp expect actual > ' > > +test_expect_success 'exclude-first-parent-only with parent already seen' ' > + git checkout --orphan test-seen && > + git rm -rf . && > + test_commit r1 && > + git checkout -b branch-f && > + test_commit f && > + git checkout test-seen && > + git merge --no-ff --no-edit -m r2 branch-f && > + git tag r2 && > + > + git rev-list --exclude-first-parent-only f ^r2 >actual && > + git rev-parse f >expect && > + test_cmp expect actual && > + > + git rev-list --exclude-first-parent-only f r1 ^r2 >actual2 && > + test_cmp expect actual2 > +' > + > test_done > Its been a while since i've looked at the code, but the rationale and test case make sense to me. thanks Reviewed-by: Jerry Zhang <[email protected]>