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

Re: Making git grep ignore binary the default

From
Jeff King <peff@peff.net>
Date
Oct 21, 2025, 07:27 UTC
Message-ID
<20251021072740.GA259661@coredump.intra.peff.net>
In-Reply-To
<CAPapNH2UeRoKF9Tm5my59MXCxUQqEp+=4wzod8kYus_FQALwjQ@mail.gmail.com>
On Mon, Oct 20, 2025 at 02:20:06PM -0300, El_Hoy wrote:
> On point 2, as Thomas points, there are many factors that might break
> a script that rely on 'git grep' directly for a dangerous task, this
> makes me think that we could add a `--porcelain` option to `git grep`
> to be used on scripts and be reliable, and it might ignore the config.

Another option here is to provide a way for scripts to override the ignore mechanism specifically (which would depend on how it is implemented). For an example, see below.

Show 5 quoted lines
> On point 3, the configuration could be made with more flexibility in
> mind, making it possible to ignore different files that are not binary
> (for example linguist-generated files). The downside of that approach
> is that it requires more configuration, while a single boolean for
> skipping binaries might be simpler. I'm ok with any approach.

One way to do this would be to provide a default pathspec for git-grep when one is not defined. Something like:

diff --git a/builtin/grep.c b/builtin/grep.c
index 13841fbf00..7b6a6ba9c6 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -42,6 +42,7 @@ static char const * const grep_usage[] = {
 };
 
 static int recurse_submodules;
+static struct strvec default_pathspec = STRVEC_INIT;
 
 static int num_threads;
 
@@ -320,6 +321,15 @@ static int grep_cmd_config(const char *var, const char *value,
 	if (!strcmp(var, "submodule.recurse"))
 		recurse_submodules = git_config_bool(var, value);
 
+	if (!strcmp(var, "grep.defaultpathspec")) {
+		if (!value)
+			return config_error_nonbool(var);
+		else if (*value)
+			strvec_push(&default_pathspec, value);
+		else
+			strvec_clear(&default_pathspec);
+	}
+
 	return st;
 }
 
@@ -1169,7 +1179,7 @@ int cmd_grep(int argc,
 	parse_pathspec(&pathspec, 0,
 		       PATHSPEC_PREFER_CWD |
 		       (opt.max_depth != -1 ? PATHSPEC_MAXDEPTH_VALID : 0),
-		       prefix, argv + i);
+		       prefix, i < argc ? argv + i : default_pathspec.v);
 	pathspec.max_depth = opt.max_depth;
 	pathspec.recursive = 1;
 	pathspec.recurse_submodules = !!recurse_submodules;

Building with that lets you do something like this in git.git:

  $ ./git grep 'added by us:'
  po/bg.po:msgid "added by us:"
  po/ca.po:msgid "added by us:"
  po/de.po:msgid "added by us:"
  po/el.po:msgid "added by us:"
  po/es.po:msgid "added by us:"
  po/fr.po:msgid "added by us:"
  po/ga.po:msgid "added by us:"
  po/id.po:msgid "added by us:"
  po/it.po:msgid "added by us:"
  po/ko.po:msgid "added by us:"
  po/pl.po:msgid "added by us:"
  po/pt_PT.po:msgid "added by us:"
  po/ru.po:msgid "added by us:"
  po/sv.po:msgid "added by us:"
  po/tr.po:msgid "added by us:"
  po/uk.po:msgid "added by us:"
  po/vi.po:msgid "added by us:"
  po/zh_CN.po:msgid "added by us:"
  po/zh_TW.po:msgid "added by us:"
  t/t7060-wtstatus.sh:    added by us:     sub_second.txt
  wt-status.c:            return _("added by us:");

  $ git config grep.defaultPathspec :^po
  $ ./git grep 'added by us:'
  t/t7060-wtstatus.sh:    added by us:     sub_second.txt
  wt-status.c:            return _("added by us:");

And then scripts override it by providing a pathspec (like "." if they
want to see everything, which conveniently also works on old versions of
Git).

It isn't _quite_ the same as an option to ignore certain paths, as it's
a default replacement, and not additive (so as soon as I ask for
everything in "foo/", then "foo/bar" will be included even if I have
"^foo/bar" in my default pathspec). I'm not sure if that is a drawback
or a feature.

There may be other rough edges. It's not something I've thought that
carefully about yet. But it just gives an idea of a possible direction.

Of course you can already do the same thing with an alias right now[1].
You just need to remember to type the alias instead of "grep". That
requires some finger retraining, but it would eliminate any script /
compatibility questions.

-Peff

[1] The alias isn't quite trivial because we want to add our pathspecs
    at the _end_ of the command-line. But I think something like:

      [alias]
      gr = "!f() { exec git grep \"$@\" :^po; }; f"

    works.
Previous: El_HoyNext: Jeff King
Message 8 of 10 in “Making git grep ignore binary the default”
  1. El_HoyOct 17, 2025
  2. Junio C HamanoOct 17, 2025
  3. Thomas BraunOct 17, 2025
  4. brian m. carlsonOct 18, 2025
  5. rsbecker@nexbridge.comOct 18, 2025
  6. Thomas BraunOct 20, 2025
  7. El_HoyOct 20, 2025
  8. Jeff KingOct 21, 2025
  9. Jeff KingOct 18, 2025
  10. Junio C HamanoOct 18, 2025

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.