* [PATCH] rev-list: skip --grep argument in early scan
@ 2026-10-21 15:12 Azuama Odinaka Maximus
2026-10-21 15:42 ` Pushkar Singh
2026-10-21 17:24 ` [PATCH v2] " Azuama Odinaka Maximus
0 siblings, 2 replies; 8+ messages in thread
From: Azuama Odinaka Maximus @ 2026-10-21 15:12 UTC (permalink / raw)
To: git; +Cc: Azuama Odinaka Maximus
Signed-off-by: Azuama Odinaka Maximus <azuama69@gmail.com>
---
builtin/rev-list.c | 2 ++
t/t6022-rev-list-missing.sh | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 0faa833fac..453d82d25c 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -771,6 +771,8 @@ int cmd_rev_list(int argc,
revs.exclude_promisor_objects = 1;
} else if (skip_prefix(arg, "--missing=", &arg)) {
parse_missing_action_value(repo, arg);
+ } else if (!strcmp(arg, "--grep")) {
+ i++;
} else if (!strcmp(arg, "--missing-only")) {
arg_missing_only = 1;
} else if (!strcmp(arg, "-z")) {
diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh
index 1bd2c3bc4f..e87678e468 100755
--- a/t/t6022-rev-list-missing.sh
+++ b/t/t6022-rev-list-missing.sh
@@ -215,6 +215,12 @@ do
'
done
+test_expect_success "--grep accepts a pattern beginning with --" '
+ git rev-list --grep=--missing-only --max-count=1 HEAD >expect &&
+ git rev-list --grep --missing-only --max-count=1 HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success "--missing-only requires --missing=print or --missing=print-info" '
test_must_fail git rev-list --missing-only --objects HEAD 2>err &&
test_grep "requires --missing=print" err
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] rev-list: skip --grep argument in early scan
2026-10-21 15:12 [PATCH] rev-list: skip --grep argument in early scan Azuama Odinaka Maximus
@ 2026-10-21 15:42 ` Pushkar Singh
2026-10-21 17:24 ` [PATCH v2] " Azuama Odinaka Maximus
1 sibling, 0 replies; 8+ messages in thread
From: Pushkar Singh @ 2026-10-21 15:42 UTC (permalink / raw)
To: Azuama Odinaka Maximus; +Cc: git
Hi,
Thanks for the patch!
One thing I noticed is that the commit message doesn't have a description.
Could you add a bit of context about the issue you're fixing and why this
change is needed? It'll make it easier for others to understand the reason
behind the patch.
> + } else if (!strcmp(arg, "--grep")) {
> + i++;
Also, could you check if the first scan needs similar handling? With --grep
--exclude-promisor-objects, the first scan might treat
--exclude-promisor-objects
as an option instead of the pattern argument to --grep. A test for this case
would help confirm whether the fix covers both scans.
Thanks!
- Pushkar
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2] rev-list: skip --grep argument in early scan
2026-10-21 15:12 [PATCH] rev-list: skip --grep argument in early scan Azuama Odinaka Maximus
2026-10-21 15:42 ` Pushkar Singh
@ 2026-10-21 17:24 ` Azuama Odinaka Maximus
2026-10-22 13:45 ` Pushkar Singh
` (2 more replies)
1 sibling, 3 replies; 8+ messages in thread
From: Azuama Odinaka Maximus @ 2026-10-21 17:24 UTC (permalink / raw)
To: git; +Cc: Azuama Odinaka Maximus
The early option scan in rev-list does not account for options
that take a separate argument. As a result, a pattern passed to
--grep can be mistaken for another option.
Skip the argument to --grep so that it is not interpreted as an
option during the early scan.
---
builtin/rev-list.c | 2 ++
t/t6022-rev-list-missing.sh | 11 +++++++++++
2 files changed, 13 insertions(+)
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 0faa833fac..453d82d25c 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -771,6 +771,8 @@ int cmd_rev_list(int argc,
revs.exclude_promisor_objects = 1;
} else if (skip_prefix(arg, "--missing=", &arg)) {
parse_missing_action_value(repo, arg);
+ } else if (!strcmp(arg, "--grep")) {
+ i++;
} else if (!strcmp(arg, "--missing-only")) {
arg_missing_only = 1;
} else if (!strcmp(arg, "-z")) {
diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh
index 1bd2c3bc4f..180e6ac766 100755
--- a/t/t6022-rev-list-missing.sh
+++ b/t/t6022-rev-list-missing.sh
@@ -215,6 +215,17 @@ do
'
done
+test_expect_success "--grep accepts a pattern beginning with --" '
+ git rev-list --grep=--missing-only --max-count=1 HEAD >expect &&
+ git rev-list --grep --missing-only --max-count=1 HEAD >actual &&
+ test_cmp expect actual
+'
+test_expect_success "--grep does not trigger --exclude-promisor-objects in early scan" '
+ git rev-list --grep=--exclude-promisor-objects --missing=print HEAD >expect &&
+ git rev-list --grep --exclude-promisor-objects --missing=print HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success "--missing-only requires --missing=print or --missing=print-info" '
test_must_fail git rev-list --missing-only --objects HEAD 2>err &&
test_grep "requires --missing=print" err
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2] rev-list: skip --grep argument in early scan
2026-10-21 17:24 ` [PATCH v2] " Azuama Odinaka Maximus
@ 2026-10-22 13:45 ` Pushkar Singh
2026-10-23 18:14 ` Junio C Hamano
2026-10-26 8:30 ` [PATCH v3] " Azuama Odinaka Maximus
2 siblings, 0 replies; 8+ messages in thread
From: Pushkar Singh @ 2026-10-22 13:45 UTC (permalink / raw)
To: Azuama Odinaka Maximus; +Cc: git
Hi Azuma,
>
> Skip the argument to --grep so that it is not interpreted as an
> option during the early scan.
> ---
Can you add a "Changes in v2" section after the --- here, summarizing
what changed from the previous version?
Also, I noticed the "Signed-off-by" line is missing in v2. Could you
add it back?
Other than that, it looks good to me.
- Pushkar
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2] rev-list: skip --grep argument in early scan
2026-10-21 17:24 ` [PATCH v2] " Azuama Odinaka Maximus
2026-10-22 13:45 ` Pushkar Singh
@ 2026-10-23 18:14 ` Junio C Hamano
2026-10-26 8:30 ` [PATCH v3] " Azuama Odinaka Maximus
2 siblings, 0 replies; 8+ messages in thread
From: Junio C Hamano @ 2026-10-23 18:14 UTC (permalink / raw)
To: Azuama Odinaka Maximus; +Cc: git
Azuama Odinaka Maximus <azuama69@gmail.com> writes:
> +test_expect_success "--grep accepts a pattern beginning with --" '
> + git rev-list --grep=--missing-only --max-count=1 HEAD >expect &&
> + git rev-list --grep --missing-only --max-count=1 HEAD >actual &&
> + test_cmp expect actual
> +'
> +test_expect_success "--grep does not trigger --exclude-promisor-objects in early scan" '
> + git rev-list --grep=--exclude-promisor-objects --missing=print HEAD >expect &&
> + git rev-list --grep --exclude-promisor-objects --missing=print HEAD >actual &&
> + test_cmp expect actual
> +'
Have a blank line between tests.
Do these tests truly verify anything beyond "the command line parser
is not broken by my commit"? There is nothing in the history that
would trigger '--missing-only'; there is no positive indication that
the pattern starting with "--" was used by '--grep' at all. The only
clue that '--missing-only' was not taken as a command line option is
that the command did not fail due to a lack of '--missing=<how>'.
The same issue exists in the second added test.
Thanks.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3] rev-list: skip --grep argument in early scan
2026-10-21 17:24 ` [PATCH v2] " Azuama Odinaka Maximus
2026-10-22 13:45 ` Pushkar Singh
2026-10-23 18:14 ` Junio C Hamano
@ 2026-10-26 8:30 ` Azuama Odinaka Maximus
2026-11-05 7:53 ` Tanga Joris
2 siblings, 1 reply; 8+ messages in thread
From: Azuama Odinaka Maximus @ 2026-10-26 8:30 UTC (permalink / raw)
To: git; +Cc: azuama69
The early option scan in rev-list does not account for options
that take a separate argument. As a result, a pattern passed to
--grep can be mistaken for another option.
Skip the argument to --grep so that it is not interpreted as an
option during the early scan.
The tests check that patterns beginning with "--" are actually
matched by --grep, including when the pattern resembles an option
that the early scan handles specially.
Signed-off-by: Azuama Odinaka Maximus <azuama69@gmail.com>
---
Changes in v3:
- Improve both regression tests to verify that --grep matches the
expected commit when its pattern begins with "--".
- Add a blank line between the tests.
builtin/rev-list.c | 2 ++
t/t6022-rev-list-missing.sh | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 0faa833fac..453d82d25c 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -771,6 +771,8 @@ int cmd_rev_list(int argc,
revs.exclude_promisor_objects = 1;
} else if (skip_prefix(arg, "--missing=", &arg)) {
parse_missing_action_value(repo, arg);
+ } else if (!strcmp(arg, "--grep")) {
+ i++;
} else if (!strcmp(arg, "--missing-only")) {
arg_missing_only = 1;
} else if (!strcmp(arg, "-z")) {
diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh
index 1bd2c3bc4f..3757bde708 100755
--- a/t/t6022-rev-list-missing.sh
+++ b/t/t6022-rev-list-missing.sh
@@ -215,6 +215,26 @@ do
'
done
+test_expect_success "--grep accepts a pattern beginning with --" '
+ test_commit --no-tag --missing-only &&
+ commit=$(git rev-parse HEAD) &&
+ echo "$commit" >expect &&
+ git rev-list --grep=--missing-only HEAD >actual &&
+ test_cmp expect actual &&
+ git rev-list --grep --missing-only HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "--grep does not trigger --exclude-promisor-objects in early scan" '
+ test_commit --no-tag --exclude-promisor-objects &&
+ commit=$(git rev-parse HEAD) &&
+ echo "$commit" >expect &&
+ git rev-list --grep=--exclude-promisor-objects --missing=print HEAD >actual &&
+ test_cmp expect actual &&
+ git rev-list --grep --exclude-promisor-objects --missing=print HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success "--missing-only requires --missing=print or --missing=print-info" '
test_must_fail git rev-list --missing-only --objects HEAD 2>err &&
test_grep "requires --missing=print" err
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3] rev-list: skip --grep argument in early scan
2026-10-26 8:30 ` [PATCH v3] " Azuama Odinaka Maximus
@ 2026-11-05 7:53 ` Tanga Joris
2026-11-05 12:09 ` [PATCH v4] rev-list: handle arguments in early option scan Azuama Odinaka Maximus
0 siblings, 1 reply; 8+ messages in thread
From: Tanga Joris @ 2026-11-05 7:53 UTC (permalink / raw)
To: Azuama Odinaka Maximus
Cc: git, Junio C Hamano, Pushkar Singh, christian.couder
Hello Azuama,
Thanks for working on this.
I applied v3 on top of master (0ffa3e35c7) with "git am -3", because
builtin/rev-list.c has changed since you sent it, so running "git am"
fails. Rebasing on master would help. I built it with NO_RUST=1.
t6022 passes, and both new tests fail when I revert only the change
in builtin/rev-list.c, so they do catch the problem.
On Mon, 26 Oct 2026 at 11:30, Azuama Odinaka Maximus <azuama69@gmail.com> wrote:
> +test_expect_success "--grep accepts a pattern beginning with --" '
> + test_commit --no-tag --missing-only &&
> + commit=$(git rev-parse HEAD) &&
These lines are indented with spaces instead of a tab. "git diff
--check" reports "indent with spaces" for all the new test lines.
> + } else if (!strcmp(arg, "--grep")) {
> + i++;
This fixes --grep, but other options that take a separate value
still have the same problem. In a repository whose only commit has
"--missing-only" as both its subject and its author name, with this
patch:
$ git rev-list --grep --missing-only HEAD
<the commit>
$ git rev-list --author --missing-only HEAD
fatal: --missing-only requires --missing=print or --missing=print-info
--committer and --grep-reflog fail the same way. In revision.c, 19
options are parsed with parse_long_opt(), which accepts the value as
a separate argument (--author, --committer, --since, --until, --skip,
--exclude and others). Should the early scan skip the value of all
of them, or is there a reason to handle only --grep? If this only fixes
--grep for now, the commit message could say so, because its first
paragraph describes the general problem.
Also, the NEEDSWORK comment just above this loop uses "--grep
--exclude-promisor-objects" as its example of what the loop gets
wrong. With this patch that example works, so the comment needs a
new example (--author would do), or it simply becomes misleading.
Thanks,
Tanga
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4] rev-list: handle arguments in early option scan
2026-11-05 7:53 ` Tanga Joris
@ 2026-11-05 12:09 ` Azuama Odinaka Maximus
0 siblings, 0 replies; 8+ messages in thread
From: Azuama Odinaka Maximus @ 2026-11-05 12:09 UTC (permalink / raw)
To: git
Cc: tangajoris, pushkarkumarsingh1970, gitster, christian.couder,
Azuama Odinaka Maximus
The early option scan in cmd_rev_list() looks for options that
affect missing-object handling before setup_revisions() parses the
command line. It must not interpret an option's separate argument
as another option.
Use parse_long_opt() to recognize revision options that take
separate arguments, and skip those arguments. Handle -n and
--default as well. Stop scanning at --, where subsequent arguments
are pathspecs.
Add tests to ensure that --grep and --author arguments beginning
with -- are not mistaken for options during the early scan.
Signed-off-by: Azuama Odinaka Maximus <azuama69@gmail.com>
---
builtin/rev-list.c | 55 +++++++++++++++++++++++++++++++++++--
t/t6022-rev-list-missing.sh | 26 ++++++++++++++++++
2 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 071a0e3cb5..4dd646050a 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -744,6 +744,47 @@ static void prepare_maximal_independent(struct rev_info *revs)
revs->no_walk = 1;
}
+static int rev_list_option_takes_argument(const char **argv)
+{
+ static const char * const options[] = {
+ "max-count",
+ "max-count-oldest",
+ "skip",
+ "max-age",
+ "since",
+ "since-as-filter",
+ "after",
+ "min-age",
+ "before",
+ "until",
+ "date",
+ "author",
+ "committer",
+ "grep-reflog",
+ "grep",
+ "encoding",
+ "glob",
+ "exclude",
+ "exclude-hidden",
+ };
+ const char *optarg;
+ size_t i;
+
+ if (!argv[1])
+ return 0;
+
+ if (!strcmp(argv[0], "-n") ||
+ !strcmp(argv[0], "--default"))
+ return 1;
+
+ for (i = 0; i < ARRAY_SIZE(options); i++) {
+ if (parse_long_opt(options[i], argv, &optarg) == 2)
+ return 1;
+ }
+
+ return 0;
+}
+
int cmd_rev_list(int argc,
const char **argv,
const char *prefix,
@@ -789,9 +830,8 @@ int cmd_rev_list(int argc,
* NEEDSWORK: The next loop is utterly broken. It tries to
* notice an option is used, but without understanding if each
* option takes an argument, which fundamentally would not
- * work. It would not know "--grep
- * --exclude-promisor-objects" is not triggering
- * "--exclude-promisor-objects" option, for example.
+ * work. It would not know that "--author --missing-only" is not
+ * triggering "--missing-only" option, for example.
*
* We really need setup_revisions() to have a mechanism to
* allow and disallow some sets of options for different
@@ -802,6 +842,15 @@ int cmd_rev_list(int argc,
*/
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
+
+ if (!strcmp(arg, "--"))
+ break;
+
+ if (rev_list_option_takes_argument(&argv[i])) {
+ i++;
+ continue;
+ }
+
if (!strcmp(arg, "--exclude-promisor-objects")) {
repo->fetch_if_missing = 0;
revs.exclude_promisor_objects = 1;
diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh
index 1bd2c3bc4f..9f995968fd 100755
--- a/t/t6022-rev-list-missing.sh
+++ b/t/t6022-rev-list-missing.sh
@@ -215,6 +215,32 @@ do
'
done
+test_expect_success "--grep accepts a pattern beginning with --" '
+ test_commit --no-tag --missing-only &&
+ commit=$(git rev-parse HEAD) &&
+ echo "$commit" >expect &&
+ git rev-list --grep=--missing-only HEAD >actual &&
+ test_cmp expect actual &&
+ git rev-list --grep --missing-only HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "--grep does not trigger --exclude-promisor-objects in early scan" '
+ test_commit --no-tag --exclude-promisor-objects &&
+ commit=$(git rev-parse HEAD) &&
+ echo "$commit" >expect &&
+ git rev-list --grep=--exclude-promisor-objects --missing=print HEAD >actual &&
+ test_cmp expect actual &&
+ git rev-list --grep --exclude-promisor-objects --missing=print HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "--author argument is not treated as an option in early scan" '
+ test_commit --no-tag author-test &&
+ git rev-list --author --missing-only HEAD >actual &&
+ test_must_be_empty actual
+'
+
test_expect_success "--missing-only requires --missing=print or --missing=print-info" '
test_must_fail git rev-list --missing-only --objects HEAD 2>err &&
test_grep "requires --missing=print" err
--
2.56.0.386.g979eb7e29a
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-11-05 12:12 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-21 15:12 [PATCH] rev-list: skip --grep argument in early scan Azuama Odinaka Maximus
2026-10-21 15:42 ` Pushkar Singh
2026-10-21 17:24 ` [PATCH v2] " Azuama Odinaka Maximus
2026-10-22 13:45 ` Pushkar Singh
2026-10-23 18:14 ` Junio C Hamano
2026-10-26 8:30 ` [PATCH v3] " Azuama Odinaka Maximus
2026-11-05 7:53 ` Tanga Joris
2026-11-05 12:09 ` [PATCH v4] rev-list: handle arguments in early option scan Azuama Odinaka Maximus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox