Skip to contentSkip to conversation

Weird behavior with git grep --recurse-submodules

PATCH Superseded Daniel Zaoui 6 participants 14 messages Jul 8, 2019 – Aug 3, 2019

lore
Share & tools
lore
#0 lore raw

Hi guys,

I work with submodules and use git grep a lot.

I noted that when it is invoked used with --recurse-submodules, the result is not as expected for the submodules. I get submodules results as if no files were modified (like --cached option) although I would expect results taking into account the modifications.

Expected behavior:
git grep --recurse-submodules string:
- git grep string // search into main repo
- for each submodule, git grep string // search into submodule

Actual behavior:
git grep --recurse-submodules string:
- git grep string // search into main repo
- for each submodule, git grep --cached string // search into submodule

Do you get the same behavior? Am I doing something wrong? Was I understandable :-)? Is it a bug?

git --version: git version 2.22.0
uname -a: Linux daniel 5.1.15-arch1-1-ARCH #1 SMP PREEMPT Tue Jun 25 04:49:39 UTC 2019 x86_64 GNU/Linux

Thanks
Daniel

#1 lore raw
Quoted 2 lines · Daniel Zaoui

Hi guys,

Hi, Daniel

Quoted 9 lines

I work with submodules and use git grep a lot.

I noted that when it is invoked used with --recurse-submodules, the result is not as expected for the submodules. I get submodules results as if no files were modified (like --cached option) although I would expect results taking into account the modifications.

Expected behavior:
git grep --recurse-submodules string:
- git grep string // search into main repo
- for each submodule, git grep string // search into submodule

Quoted 6 lines

Actual behavior:
git grep --recurse-submodules string:
- git grep string // search into main repo
- for each submodule, git grep --cached string // search into submodule

Do you get the same behavior? Am I doing something wrong? Was I understandable :-)? Is it a bug?

It seems git-grep was taking into account the worktree modifications in submodules before f9ee2fc ("grep: recurse in-process using 'struct repository'", 02-08-2017). I'm not sure, thought, if this behavior change was a bug during the conversion or a project decision.

CC-ing Brandon, in case he has other inputs

Quoted 5 lines

git --version: git version 2.22.0
uname -a: Linux daniel 5.1.15-arch1-1-ARCH #1 SMP PREEMPT Tue Jun 25 04:49:39 UTC 2019 x86_64 GNU/Linux

Thanks
Daniel

Best,
Matheus

#2 lore raw

[cC:ing Brandon via his current email address, as per .mailmap]

Quoted 38 lines · Matheus Tavares Bernardino
Quoted 2 lines · Daniel Zaoui

Hi guys,

Hi, Daniel

Quoted 9 lines

I work with submodules and use git grep a lot.

I noted that when it is invoked used with --recurse-submodules, the result is not as expected for the submodules. I get submodules results as if no files were modified (like --cached option) although I would expect results taking into account the modifications.

Expected behavior:
git grep --recurse-submodules string:
- git grep string // search into main repo
- for each submodule, git grep string // search into submodule

Quoted 6 lines

Actual behavior:
git grep --recurse-submodules string:
- git grep string // search into main repo
- for each submodule, git grep --cached string // search into submodule

Do you get the same behavior? Am I doing something wrong? Was I understandable :-)? Is it a bug?

It seems git-grep was taking into account the worktree modifications in submodules before f9ee2fc ("grep: recurse in-process using 'struct repository'", 02-08-2017). I'm not sure, thought, if this behavior change was a bug during the conversion or a project decision.

CC-ing Brandon, in case he has other inputs

Quoted 5 lines

git --version: git version 2.22.0
uname -a: Linux daniel 5.1.15-arch1-1-ARCH #1 SMP PREEMPT Tue Jun 25 04:49:39 UTC 2019 x86_64 GNU/Linux

Thanks
Daniel

Best,
Matheus

#3 lore raw

Hi Matheus,

Thank you for your response.

I really hope the change Brandon made is not a project decision. At least, it does seem to me like a bug.

How do you recommend me to solve this issue? Is there some place where I can check if some bug ticket has been created on this matter? I didn't find anything in the mailing list archives about this.

BR
Daniel

Quoted 12 lines · On Wed, 10 Jul 2019 13:14:18 +0200 (CEST) Johannes Schindelin…

[cC:ing Brandon via his current email address, as per .mailmap]

On Wed, 10 Jul 2019, Matheus Tavares Bernardino wrote:

[...]
[...]
[...]
[...]
[...]
[...]
[...]

#4 lore raw
Quoted 2 lines · Daniel Zaoui

Hi Matheus,

Hi, Daniel

I'm sorry, your last message went to my spam folder for some reason :(

Quoted 5 lines

Thank you for your response.

I really hope the change Brandon made is not a project decision. At least, it does seem to me like a bug.

How do you recommend me to solve this issue? Is there some place where I can check if some bug ticket has been created on this matter? I didn't find anything in the mailing list archives about this.

I think I manage to solve the bug with this[1] patch. I'm going to ask my GSoC mentors to take a look and then I'll send it to the mailing list :) Thanks for reporting it.

Best,
Matheus

[1]: https://github.com/matheustavares/git/commit/37aeeb3ab86b5dfebfaafeb98d34e379341a529d

#5 lore raw

PATCH 1/1 grep: fix worktree case in submodules

Running git-grep with --recurse-submodules results in a cached grep for the submodules even when --cached is not used. This makes all modifications in submodules' tracked files be always ignored when grepping. Solve that making git-grep respect the cached option when invoking grep_cache() inside grep_submodule(). Also, add tests to ensure that the desired behavior is performed.

---
 builtin/grep.c                     | 10 ++++++----
 t/t7814-grep-recurse-submodules.sh | 21 +++++++++++++++++++++
 2 files changed, 27 insertions(+), 4 deletions(-)
builtin/grep.c +6 -4
index 560051784e..2699001fbd 100644
@@ -403,7 +403,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 static int grep_submodule(struct grep_opt *opt,
 			  const struct pathspec *pathspec,
 			  const struct object_id *oid,
-			  const char *filename, const char *path)
+			  const char *filename, const char *path, int cached)
 {
 	struct repository subrepo;
 	struct repository *superproject = opt->repo;
@@ -475,7 +475,7 @@ static int grep_submodule(struct grep_opt *opt,
 		strbuf_release(&base);
 		free(data);
 	} else {
-		hit = grep_cache(&subopt, pathspec, 1);
+		hit = grep_cache(&subopt, pathspec, cached);
 	}
 
 	repo_clear(&subrepo);
@@ -523,7 +523,8 @@ static int grep_cache(struct grep_opt *opt,
 			}
 		} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
 			   submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
-			hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
+			hit |= grep_submodule(opt, pathspec, NULL, ce->name,
+					      ce->name, cached);
 		} else {
 			continue;
 		}
@@ -598,7 +599,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 			free(data);
 		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
 			hit |= grep_submodule(opt, pathspec, &entry.oid,
-					      base->buf, base->buf + tn_len);
+					      base->buf, base->buf + tn_len,
+					      1); /* ignored */
 		}
 
 		strbuf_setlen(base, old_baselen);
t/t7814-grep-recurse-submodules.sh +21 -0
index a11366b4ce..946f91fa57 100755
@@ -408,4 +408,25 @@ test_expect_success 'grep --recurse-submodules with submodules without .gitmodul
 	test_cmp expect actual
 '
 
+reset_and_clean () {
+	git reset --hard &&
+	git clean -fd &&
+	git submodule foreach --recursive 'git reset --hard' &&
+	git submodule foreach --recursive 'git clean -fd'
+}
+
+test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
+	reset_and_clean &&
+	echo "A modified line in submodule" >>submodule/a &&
+	echo "submodule/a:A modified line in submodule" >expect &&
+	git grep --recurse-submodules "A modified line in submodule" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
+	reset_and_clean &&
+	echo "A modified line in submodule" >>submodule/a &&
+	test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
+	test_must_be_empty actual
+'
 test_done
Signature · 1 line
2.22.0
#6 lore raw

Re: [GSoC][PATCH] grep: fix worktree case in submodules

builtin/grep.c static int grep_submodule(struct grep_opt *opt, · line 479

Quoted 7 lines · Matheus Tavares
builtin/grep.c +1 -1
@@ -475,7 +475,7 @@ static int grep_submodule(struct grep_opt *opt,
 		strbuf_release(&base);
 		free(data);
 	} else {
-		hit = grep_cache(&subopt, pathspec, 1);
+		hit = grep_cache(&subopt, pathspec, cached);
 	}

Interesting. It appears to me that this has always searched in submodule index and never working tree. I am not sure if there was any specific reason to avoid looking into the working tree files.

Passing the 'cached' bit down from grep_cache() does look like a sensible way to go.

Quoted 11 lines
builtin/grep.c +2 -1
@@ -523,7 +523,8 @@ static int grep_cache(struct grep_opt *opt,
 			}
 		} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
 			   submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
-			hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
+			hit |= grep_submodule(opt, pathspec, NULL, ce->name,
+					      ce->name, cached);
 		} else {
 			continue;
 		}

builtin/grep.c static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, · line 603

Quoted 6 lines
builtin/grep.c +2 -1
@@ -598,7 +599,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 			free(data);
 		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
 			hit |= grep_submodule(opt, pathspec, &entry.oid,
-					      base->buf, base->buf + tn_len);
+					      base->buf, base->buf + tn_len,
+					      1); /* ignored */

The trailing comment is misleading. In the context of reviewing this patch, we can probably tell it applies only to that "1", but if you read only the postimage, the "ignored" comment looks as if the call itself is somehow ignored by somebody unspecified. It is not clear at all that it is only about the final parameter.

If you must...

		hit |= grep_submodule(opt, pathspec, &entry.oid,
				      base->buf, base->buf + tn_len,
				      1 /* ignored */);

... is a reasonable way to write it.

t/t7814-grep-recurse-submodules.sh test_expect_success 'grep --recurse-submodules with submodules without .gitmodul · line 415

Quoted 13 lines
t/t7814-grep-recurse-submodules.sh +5 -0
index a11366b4ce..946f91fa57 100755
@@ -408,4 +408,25 @@ test_expect_success 'grep --recurse-submodules with submodules without .gitmodul
 	test_cmp expect actual
 '
 
+reset_and_clean () {
+	git reset --hard &&
+	git clean -fd &&
+	git submodule foreach --recursive 'git reset --hard' &&
+	git submodule foreach --recursive 'git clean -fd'

Do we need two separate foreach, instread of a single one that does both reset and clean (i.e. "git reset --hard && git clean -f -d")?

#7 lore raw

Re: [GSoC][PATCH] grep: fix worktree case in submodules

Quoted 17 lines · Junio C Hamano

builtin/grep.c static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, · line 603

Quoted 7 lines · Matheus Tavares
builtin/grep.c +2 -1
@@ -598,7 +599,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                      free(data);
              } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
                      hit |= grep_submodule(opt, pathspec, &entry.oid,
-                                           base->buf, base->buf + tn_len);
+                                           base->buf, base->buf + tn_len,
+                                           1); /* ignored */

The trailing comment is misleading. In the context of reviewing this patch, we can probably tell it applies only to that "1", but if you read only the postimage, the "ignored" comment looks as if the call itself is somehow ignored by somebody unspecified. It is not clear at all that it is only about the final parameter.

Quoted 5 lines

If you must...

                hit |= grep_submodule(opt, pathspec, &entry.oid,
                                      base->buf, base->buf + tn_len,
                                      1 /* ignored */);

Yeah, I suggested adding an "/* ignored */" comment, but I was indeed thinking about something like this.

Quoted 1 line

... is a reasonable way to write it.

#8 lore raw

Re: [GSoC][PATCH] grep: fix worktree case in submodules

Quoted 18 lines · Christian Couder
Quoted 17 lines · Junio C Hamano

builtin/grep.c static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, · line 603

Quoted 7 lines · Matheus Tavares
builtin/grep.c +2 -1
@@ -598,7 +599,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                      free(data);
              } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
                      hit |= grep_submodule(opt, pathspec, &entry.oid,
-                                           base->buf, base->buf + tn_len);
+                                           base->buf, base->buf + tn_len,
+                                           1); /* ignored */

The trailing comment is misleading. In the context of reviewing this patch, we can probably tell it applies only to that "1", but if you read only the postimage, the "ignored" comment looks as if the call itself is somehow ignored by somebody unspecified. It is not clear at all that it is only about the final parameter.

Quoted 10 lines
Quoted 5 lines

If you must...

                hit |= grep_submodule(opt, pathspec, &entry.oid,
                                      base->buf, base->buf + tn_len,
                                      1 /* ignored */);

Yeah, I suggested adding an "/* ignored */" comment, but I was indeed thinking about something like this.

Quoted 1 line

... is a reasonable way to write it.

Thanks. In this case, I am not sure if the comment here really helps. If anything, shouldn't there be a comment near the top of grep_submodule() that says 'cached bit is meaningful only when you feed an empty oid, aka "not grepping inside a tree object"'?

#9 lore raw

Re: [GSoC][PATCH] grep: fix worktree case in submodules

Quoted 30 lines · Junio C Hamano
Quoted 27 lines · Christian Couder
Quoted 17 lines · Junio C Hamano

builtin/grep.c static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, · line 603

Quoted 7 lines · Matheus Tavares
builtin/grep.c +2 -1
@@ -598,7 +599,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                      free(data);
              } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
                      hit |= grep_submodule(opt, pathspec, &entry.oid,
-                                           base->buf, base->buf + tn_len);
+                                           base->buf, base->buf + tn_len,
+                                           1); /* ignored */

The trailing comment is misleading. In the context of reviewing this patch, we can probably tell it applies only to that "1", but if you read only the postimage, the "ignored" comment looks as if the call itself is somehow ignored by somebody unspecified. It is not clear at all that it is only about the final parameter.

Quoted 5 lines

If you must...

                hit |= grep_submodule(opt, pathspec, &entry.oid,
                                      base->buf, base->buf + tn_len,
                                      1 /* ignored */);

Yeah, I suggested adding an "/* ignored */" comment, but I was indeed thinking about something like this.

Quoted 6 lines
Quoted 1 line
Quoted 1 line

... is a reasonable way to write it.

Thanks. In this case, I am not sure if the comment here really helps. If anything, shouldn't there be a comment near the top of grep_submodule() that says 'cached bit is meaningful only when you feed an empty oid, aka "not grepping inside a tree object"'?

Right, it makes sense. I'll add that.

#10 lore raw

Re: [GSoC][PATCH] grep: fix worktree case in submodules

In reply to Junio C Hamano
Quoted 14 lines · Junio C Hamano

builtin/grep.c static int grep_submodule(struct grep_opt *opt, · line 479

Quoted 7 lines · Matheus Tavares
builtin/grep.c +1 -1
@@ -475,7 +475,7 @@ static int grep_submodule(struct grep_opt *opt,
              strbuf_release(&base);
              free(data);
      } else {
-             hit = grep_cache(&subopt, pathspec, 1);
+             hit = grep_cache(&subopt, pathspec, cached);
      }

Interesting. It appears to me that this has always searched in submodule index and never working tree. I am not sure if there was any specific reason to avoid looking into the working tree files.

It seems that git-grep was taking the worktree into account before f9ee2fc ("grep: recurse in-process using 'struct repository'", 02-08-2017). So maybe it was just a mistake during the in-process conversion.

Quoted 27 lines

Passing the 'cached' bit down from grep_cache() does look like a sensible way to go.

Quoted 11 lines
builtin/grep.c +2 -1
@@ -523,7 +523,8 @@ static int grep_cache(struct grep_opt *opt,
                      }
              } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
                         submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
-                     hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
+                     hit |= grep_submodule(opt, pathspec, NULL, ce->name,
+                                           ce->name, cached);
              } else {
                      continue;
              }

builtin/grep.c static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, · line 603

Quoted 6 lines
builtin/grep.c +2 -1
@@ -598,7 +599,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                      free(data);
              } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
                      hit |= grep_submodule(opt, pathspec, &entry.oid,
-                                           base->buf, base->buf + tn_len);
+                                           base->buf, base->buf + tn_len,
+                                           1); /* ignored */

The trailing comment is misleading. In the context of reviewing this patch, we can probably tell it applies only to that "1", but if you read only the postimage, the "ignored" comment looks as if the call itself is somehow ignored by somebody unspecified. It is not clear at all that it is only about the final parameter.

Quoted 7 lines

If you must...

                hit |= grep_submodule(opt, pathspec, &entry.oid,
                                      base->buf, base->buf + tn_len,
                                      1 /* ignored */);

... is a reasonable way to write it.

Right, thanks.

Quoted 8 lines
Quoted 8 lines
t/t7814-grep-recurse-submodules.sh +0 -0
index a11366b4ce..946f91fa57 100755
@@ -408,4 +408,25 @@ test_expect_success 'grep --recurse-submodules with submodules without .gitmodul
      test_cmp expect actual
 '
 
Quoted 8 lines

t/t7814-grep-recurse-submodules.sh test_expect_success 'grep --recurse-submodules with submodules without .gitmodul · line 415

Quoted 5 lines
t/t7814-grep-recurse-submodules.sh +5 -0
+reset_and_clean () {
+     git reset --hard &&
+     git clean -fd &&
+     git submodule foreach --recursive 'git reset --hard' &&
+     git submodule foreach --recursive 'git clean -fd'

Do we need two separate foreach, instread of a single one that does both reset and clean (i.e. "git reset --hard && git clean -f -d")?

Indeed! Thanks. I'll send a v2 addressing both comments.

#11 lore raw

PATCH v2 1/1 grep: fix worktree case in submodules

In reply to Matheus Tavares

Running git-grep with --recurse-submodules results in a cached grep for the submodules even when --cached is not used. This makes all modifications in submodules' tracked files be always ignored when grepping. Solve that making git-grep respect the cached option when invoking grep_cache() inside grep_submodule(). Also, add tests to ensure that the desired behavior is performed.

---
Changes in v2:
- repositioned the '/* ignored */' comment to avoid ambiguity
- joined git clean and git reset invokations in a single git submodule foreach.

travis build: https://travis-ci.org/matheustavares/git/builds/565749070

builtin/grep.c | 10 ++++++----

 t/t7814-grep-recurse-submodules.sh | 20 ++++++++++++++++++++
 2 files changed, 26 insertions(+), 4 deletions(-)
builtin/grep.c +6 -4
index 560051784e..d9866dd936 100644
@@ -403,7 +403,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 static int grep_submodule(struct grep_opt *opt,
 			  const struct pathspec *pathspec,
 			  const struct object_id *oid,
-			  const char *filename, const char *path)
+			  const char *filename, const char *path, int cached)
 {
 	struct repository subrepo;
 	struct repository *superproject = opt->repo;
@@ -475,7 +475,7 @@ static int grep_submodule(struct grep_opt *opt,
 		strbuf_release(&base);
 		free(data);
 	} else {
-		hit = grep_cache(&subopt, pathspec, 1);
+		hit = grep_cache(&subopt, pathspec, cached);
 	}
 
 	repo_clear(&subrepo);
@@ -523,7 +523,8 @@ static int grep_cache(struct grep_opt *opt,
 			}
 		} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
 			   submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
-			hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
+			hit |= grep_submodule(opt, pathspec, NULL, ce->name,
+					      ce->name, cached);
 		} else {
 			continue;
 		}
@@ -598,7 +599,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 			free(data);
 		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
 			hit |= grep_submodule(opt, pathspec, &entry.oid,
-					      base->buf, base->buf + tn_len);
+					      base->buf, base->buf + tn_len,
+					      1 /* ignored */);
 		}
 
 		strbuf_setlen(base, old_baselen);
t/t7814-grep-recurse-submodules.sh +20 -0
index a11366b4ce..edb64690e6 100755
@@ -408,4 +408,24 @@ test_expect_success 'grep --recurse-submodules with submodules without .gitmodul
 	test_cmp expect actual
 '
 
+reset_and_clean () {
+	git reset --hard &&
+	git clean -fd &&
+	git submodule foreach --recursive 'git reset --hard && git clean -fd'
+}
+
+test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
+	reset_and_clean &&
+	echo "A modified line in submodule" >>submodule/a &&
+	echo "submodule/a:A modified line in submodule" >expect &&
+	git grep --recurse-submodules "A modified line in submodule" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
+	reset_and_clean &&
+	echo "A modified line in submodule" >>submodule/a &&
+	test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
+	test_must_be_empty actual
+'
 test_done
Signature · 1 line
2.22.0
#12 lore raw

PATCH v3 1/1 grep: fix worktree case in submodules

Running git-grep with --recurse-submodules results in a cached grep for the submodules even when --cached is not used. This makes all modifications in submodules' tracked files be always ignored when grepping. Solve that making git-grep respect the cached option when invoking grep_cache() inside grep_submodule(). Also, add tests to ensure that the desired behavior is performed.

---
Changes in v3:
- Replaced the "\* ignored *\" comment by a more meaningful note at the top of grep_submodule()

builtin/grep.c | 13 +++++++++----

 t/t7814-grep-recurse-submodules.sh | 20 ++++++++++++++++++++
 2 files changed, 29 insertions(+), 4 deletions(-)
builtin/grep.c +9 -4
index 560051784e..df8cdecdae 100644
@@ -400,10 +400,14 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 		     struct tree_desc *tree, struct strbuf *base, int tn_len,
 		     int check_attr);
 
+/*
+ * The cached bit is only meaningful when a NULL oid is given (i.e. when not
+ * grepping inside a tree object).
+ */
 static int grep_submodule(struct grep_opt *opt,
 			  const struct pathspec *pathspec,
 			  const struct object_id *oid,
-			  const char *filename, const char *path)
+			  const char *filename, const char *path, int cached)
 {
 	struct repository subrepo;
 	struct repository *superproject = opt->repo;
@@ -475,7 +479,7 @@ static int grep_submodule(struct grep_opt *opt,
 		strbuf_release(&base);
 		free(data);
 	} else {
-		hit = grep_cache(&subopt, pathspec, 1);
+		hit = grep_cache(&subopt, pathspec, cached);
 	}
 
 	repo_clear(&subrepo);
@@ -523,7 +527,8 @@ static int grep_cache(struct grep_opt *opt,
 			}
 		} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
 			   submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
-			hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
+			hit |= grep_submodule(opt, pathspec, NULL, ce->name,
+					      ce->name, cached);
 		} else {
 			continue;
 		}
@@ -598,7 +603,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 			free(data);
 		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
 			hit |= grep_submodule(opt, pathspec, &entry.oid,
-					      base->buf, base->buf + tn_len);
+					      base->buf, base->buf + tn_len, 1);
 		}
 
 		strbuf_setlen(base, old_baselen);
t/t7814-grep-recurse-submodules.sh +20 -0
index a11366b4ce..edb64690e6 100755
@@ -408,4 +408,24 @@ test_expect_success 'grep --recurse-submodules with submodules without .gitmodul
 	test_cmp expect actual
 '
 
+reset_and_clean () {
+	git reset --hard &&
+	git clean -fd &&
+	git submodule foreach --recursive 'git reset --hard && git clean -fd'
+}
+
+test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
+	reset_and_clean &&
+	echo "A modified line in submodule" >>submodule/a &&
+	echo "submodule/a:A modified line in submodule" >expect &&
+	git grep --recurse-submodules "A modified line in submodule" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
+	reset_and_clean &&
+	echo "A modified line in submodule" >>submodule/a &&
+	test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
+	test_must_be_empty actual
+'
 test_done
Signature · 1 line
2.22.0
#13 lore raw
In reply to Matheus Tavares Bernardino
Quoted 13 lines · Matheus Tavares Bernardino
Quoted 2 lines · Daniel Zaoui

Hi Matheus,

Hi, Daniel

I'm sorry, your last message went to my spam folder for some reason :(

Quoted 4 lines

Thank you for your response.

I really hope the change Brandon made is not a project decision. At least, it does seem to me like a bug.

Since I'm the one who originally implemented the --recurse-submodules feature to git grep back in
0281e487f (grep: optionally recurse into submodules, 2016-12-16) and then subsequently changed
the implementation to do the recursion in process in f9ee2fc ("grep:
recurse in-process using
'struct repository'", 02-08-2017) I can say it was definitely a bug I introduced during the conversion
as I don't believe I would have intended to introduce that change of behavior (especially without
documenting it).

Quoted 10 lines
Quoted 1 line

How do you recommend me to solve this issue? Is there some place where I can check if some bug ticket has been created on this matter? I didn't find anything in the mailing list archives about this.

I think I manage to solve the bug with this[1] patch. I'm going to ask my GSoC mentors to take a look and then I'll send it to the mailing list :) Thanks for reporting it.

Best,
Matheus

[1]: https://github.com/matheustavares/git/commit/37aeeb3ab86b5dfebfaafeb98d34e379341a529d