git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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>
Previous: Junio C Hamano
Message 3 of 3 in “Bug report - git rev-list --exclude-first-parent-only [SEC=UNOFFICIAL]”
  1. Michael HoreJul 2, 2026
  2. Junio C HamanoJul 3, 2026
  3. Jerry ZhangJul 21, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.