Re: Bug report - git rev-list --exclude-first-parent-only [SEC=UNOFFICIAL]
- From
Jerry Zhang <jerry@skydio.com>
- Date
- Jul 21, 2026, 00:35 UTC
- Message-ID
- <CAMKO5Cu0i3UKT61th3ZUiiQTkPa+YtxGQAQSXJjNWGWaTs8OGg@mail.gmail.com>
- In-Reply-To
- <xmqqbjcnizr1.fsf@gitster.g>
On Fri, Jul 3, 2026 at 1:28 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 37 quoted lines
> > Michael Hore <Michael.Hore@asic.gov.au> 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.
Show 63 quoted lines
>
> 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 <jerry@skydio.com>