* [PATCH 1/3] git-config.adoc: fix paragraph break
2026-06-08 13:57 [PATCH 0/3] config: allow disabling config includes Derrick Stolee via GitGitGadget
@ 2026-06-08 13:57 ` Derrick Stolee via GitGitGadget
2026-06-08 13:57 ` [PATCH 2/3] config: add GIT_CONFIG_INCLUDES Derrick Stolee via GitGitGadget
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Derrick Stolee via GitGitGadget @ 2026-06-08 13:57 UTC (permalink / raw)
To: git; +Cc: gitster, Derrick Stolee, Derrick Stolee
From: Derrick Stolee <stolee@gmail.com>
The bulletted list about environment variables is missing a '+' between
some paragraphs that belong to the same bullet item. Without it, the
bulletted list is rendered as two separate lists with "See also FILES."
as a normal paragraph between them. Adding '+' unifies the lists.
Signed-off-by: Derrick Stolee <stolee@gmail.com>
---
Documentation/git-config.adoc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc
index 00545b2054..044d776613 100644
--- a/Documentation/git-config.adoc
+++ b/Documentation/git-config.adoc
@@ -476,7 +476,7 @@ GIT_CONFIG_SYSTEM::
GIT_CONFIG_NOSYSTEM::
Whether to skip reading settings from the system-wide
$(prefix)/etc/gitconfig file. See linkgit:git[1] for details.
-
++
See also <<FILES>>.
GIT_CONFIG_COUNT::
--
gitgitgadget
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 2/3] config: add GIT_CONFIG_INCLUDES
2026-06-08 13:57 [PATCH 0/3] config: allow disabling config includes Derrick Stolee via GitGitGadget
2026-06-08 13:57 ` [PATCH 1/3] git-config.adoc: fix paragraph break Derrick Stolee via GitGitGadget
@ 2026-06-08 13:57 ` Derrick Stolee via GitGitGadget
2026-06-08 14:34 ` Patrick Steinhardt
2026-06-08 13:57 ` [PATCH 3/3] git: add --no-includes top-level option Derrick Stolee via GitGitGadget
2026-06-08 22:51 ` [PATCH 0/3] config: allow disabling config includes Jeff King
3 siblings, 1 reply; 8+ messages in thread
From: Derrick Stolee via GitGitGadget @ 2026-06-08 13:57 UTC (permalink / raw)
To: git; +Cc: gitster, Derrick Stolee, Derrick Stolee
From: Derrick Stolee <stolee@gmail.com>
The config keys 'include.path' and 'includeIf.*' allow users to specify
config stored in a location outside of the typical list of config files
(system, global, local, etc.). For example, users who accept the risk
can specify helpful aliases via a file checked into the repo by pointing
'include.path' to the position of that file in the working directory.
This is dangerous, but people do it.
What becomes tricky is that this modifies all Git behavior, including
operations that are intended to be limited in activity or sandboxed in
some way. These include directives can provide surprising changes to
behavior, especially when expecting a specific list of allowed file
accesses. This could lead to failed builds, for instance.
To allow for these user-desired features when they are running commands,
add a new GIT_CONFIG_INCLUDES environment variable that disables these
redirections of config when set to zero. This variable can be set by
automation, such as build tooling, to avoid these strange behaviors.
This could be considered a recommended option for tools executing Git
commands, the same as GIT_ADVICE=0.
Signed-off-by: Derrick Stolee <stolee@gmail.com>
---
Documentation/git-config.adoc | 5 +++++
config.c | 7 ++++++-
environment.h | 6 ++++++
t/t1305-config-include.sh | 31 +++++++++++++++++++++++++++++++
4 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc
index 044d776613..c9b5159501 100644
--- a/Documentation/git-config.adoc
+++ b/Documentation/git-config.adoc
@@ -502,6 +502,11 @@ GIT_CONFIG::
historical compatibility; there is generally no reason to use it
instead of the `--file` option.
+GIT_CONFIG_INCLUDES::
+ If GIT_CONFIG_INCLUDES is set to 0, then Git will not follow
+ `include.path` or `includeIf.*.path` directives when reading
+ configuration files.
+
[[EXAMPLES]]
EXAMPLES
--------
diff --git a/config.c b/config.c
index a1b92fe083..85edd05672 100644
--- a/config.c
+++ b/config.c
@@ -1595,9 +1595,14 @@ int config_with_options(config_fn_t fn, void *data,
const struct config_options *opts)
{
struct config_include_data inc = CONFIG_INCLUDE_INIT;
+ int respect_includes = opts->respect_includes;
int ret;
- if (opts->respect_includes) {
+ if (respect_includes &&
+ !git_env_bool(CONFIG_INCLUDES_ENVIRONMENT, 1))
+ respect_includes = 0;
+
+ if (respect_includes) {
inc.fn = fn;
inc.data = data;
inc.opts = opts;
diff --git a/environment.h b/environment.h
index 9eb97b3869..2c57ae2533 100644
--- a/environment.h
+++ b/environment.h
@@ -52,6 +52,12 @@
*/
#define GIT_ADVICE_ENVIRONMENT "GIT_ADVICE"
+/*
+ * Environment variable used to prevent following include.path or includeIf.*
+ * config directives.
+ */
+#define CONFIG_INCLUDES_ENVIRONMENT "GIT_CONFIG_INCLUDES"
+
/*
* Environment variable used in handshaking the wire protocol.
* Contains a colon ':' separated list of keys with optional values
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index f3892578e4..270e4b89ab 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -396,4 +396,35 @@ test_expect_success 'onbranch without repository but explicit nonexistent Git di
test_must_fail nongit git --git-dir=nonexistent config get foo.bar
'
+test_expect_success 'GIT_CONFIG_INCLUDES=0 disables include.path and includeIf' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set include.path config.inc &&
+ git config set "includeIf.gitdir:*.path" config2.inc &&
+ git config set -f .git/config.inc foo.bar from-include &&
+ git config set -f .git/config2.inc foo.baz from-includeif &&
+ git config get foo.bar &&
+ git config get foo.baz &&
+ test_must_fail env GIT_CONFIG_INCLUDES=0 git config get foo.bar &&
+ test_must_fail env GIT_CONFIG_INCLUDES=0 git config get foo.baz &&
+ git config get --includes foo.bar &&
+ test_must_fail env GIT_CONFIG_INCLUDES=0 git config get --includes foo.bar
+ )
+'
+
+test_expect_success 'GIT_CONFIG_INCLUDES=0 blocks included alias override' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set alias.test false &&
+ git config set include.path config.inc &&
+ git config set -f .git/config.inc alias.test status &&
+ git test &&
+ test_must_fail env GIT_CONFIG_INCLUDES=0 git test
+ )
+'
+
test_done
--
gitgitgadget
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 2/3] config: add GIT_CONFIG_INCLUDES
2026-06-08 13:57 ` [PATCH 2/3] config: add GIT_CONFIG_INCLUDES Derrick Stolee via GitGitGadget
@ 2026-06-08 14:34 ` Patrick Steinhardt
2026-06-08 19:38 ` Derrick Stolee
0 siblings, 1 reply; 8+ messages in thread
From: Patrick Steinhardt @ 2026-06-08 14:34 UTC (permalink / raw)
To: Derrick Stolee via GitGitGadget; +Cc: git, gitster, Derrick Stolee
On Mon, Jun 08, 2026 at 01:57:05PM +0000, Derrick Stolee via GitGitGadget wrote:
> From: Derrick Stolee <stolee@gmail.com>
>
> The config keys 'include.path' and 'includeIf.*' allow users to specify
> config stored in a location outside of the typical list of config files
> (system, global, local, etc.). For example, users who accept the risk
> can specify helpful aliases via a file checked into the repo by pointing
> 'include.path' to the position of that file in the working directory.
> This is dangerous, but people do it.
Huh, I never even considered this use case. But of course, this is
possible, even though it's quite scary.
> What becomes tricky is that this modifies all Git behavior, including
> operations that are intended to be limited in activity or sandboxed in
> some way. These include directives can provide surprising changes to
> behavior, especially when expecting a specific list of allowed file
> accesses. This could lead to failed builds, for instance.
>
> To allow for these user-desired features when they are running commands,
> add a new GIT_CONFIG_INCLUDES environment variable that disables these
> redirections of config when set to zero. This variable can be set by
> automation, such as build tooling, to avoid these strange behaviors.
> This could be considered a recommended option for tools executing Git
> commands, the same as GIT_ADVICE=0.
I don't know about this part though. I could see use cases where the
tools _should_ read the project-relative configuration. It might also be
the case that the user may want to evaluate some includes, but not all
of them.
That raises the question whether we can introduce the configuration in a
way that it allows a bit more flexibility than just "yes"/"no", like for
example an allow-list of locations that should be evaluated. But maybe
I'm overthinking this.
Patrick
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] config: add GIT_CONFIG_INCLUDES
2026-06-08 14:34 ` Patrick Steinhardt
@ 2026-06-08 19:38 ` Derrick Stolee
2026-06-09 6:06 ` Patrick Steinhardt
0 siblings, 1 reply; 8+ messages in thread
From: Derrick Stolee @ 2026-06-08 19:38 UTC (permalink / raw)
To: Patrick Steinhardt, Derrick Stolee via GitGitGadget; +Cc: git, gitster
On 6/8/2026 10:34 AM, Patrick Steinhardt wrote:
> On Mon, Jun 08, 2026 at 01:57:05PM +0000, Derrick Stolee via GitGitGadget wrote:
>> From: Derrick Stolee <stolee@gmail.com>
>>
>> The config keys 'include.path' and 'includeIf.*' allow users to specify
>> config stored in a location outside of the typical list of config files
>> (system, global, local, etc.). For example, users who accept the risk
>> can specify helpful aliases via a file checked into the repo by pointing
>> 'include.path' to the position of that file in the working directory.
>> This is dangerous, but people do it.
>
> Huh, I never even considered this use case. But of course, this is
> possible, even though it's quite scary.
>
>> What becomes tricky is that this modifies all Git behavior, including
>> operations that are intended to be limited in activity or sandboxed in
>> some way. These include directives can provide surprising changes to
>> behavior, especially when expecting a specific list of allowed file
>> accesses. This could lead to failed builds, for instance.
>>
>> To allow for these user-desired features when they are running commands,
>> add a new GIT_CONFIG_INCLUDES environment variable that disables these
>> redirections of config when set to zero. This variable can be set by
>> automation, such as build tooling, to avoid these strange behaviors.
>> This could be considered a recommended option for tools executing Git
>> commands, the same as GIT_ADVICE=0.
>
> I don't know about this part though. I could see use cases where the
> tools _should_ read the project-relative configuration. It might also be
> the case that the user may want to evaluate some includes, but not all
> of them.
True. I'm not confident that we should recommend this environment in all
cases.
> That raises the question whether we can introduce the configuration in a
> way that it allows a bit more flexibility than just "yes"/"no", like for
> example an allow-list of locations that should be evaluated. But maybe
> I'm overthinking this.
I see. So we can say "avoid including into the repository worktree" but
that will probably be incomplete.
There is room for nuance in future expansions, if we can find a creative
way to handle that nuance. For now, I think I would still want an ability
to turn the entire feature off, at least for certain tools that care.
Thanks,
-Stolee
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] config: add GIT_CONFIG_INCLUDES
2026-06-08 19:38 ` Derrick Stolee
@ 2026-06-09 6:06 ` Patrick Steinhardt
0 siblings, 0 replies; 8+ messages in thread
From: Patrick Steinhardt @ 2026-06-09 6:06 UTC (permalink / raw)
To: Derrick Stolee; +Cc: Derrick Stolee via GitGitGadget, git, gitster
On Mon, Jun 08, 2026 at 03:38:55PM -0400, Derrick Stolee wrote:
> On 6/8/2026 10:34 AM, Patrick Steinhardt wrote:
> > On Mon, Jun 08, 2026 at 01:57:05PM +0000, Derrick Stolee via GitGitGadget wrote:
> > That raises the question whether we can introduce the configuration in a
> > way that it allows a bit more flexibility than just "yes"/"no", like for
> > example an allow-list of locations that should be evaluated. But maybe
> > I'm overthinking this.
> I see. So we can say "avoid including into the repository worktree" but
> that will probably be incomplete.
>
> There is room for nuance in future expansions, if we can find a creative
> way to handle that nuance. For now, I think I would still want an ability
> to turn the entire feature off, at least for certain tools that care.
Yup, that's fine with me. Thanks!
Patrick
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/3] git: add --no-includes top-level option
2026-06-08 13:57 [PATCH 0/3] config: allow disabling config includes Derrick Stolee via GitGitGadget
2026-06-08 13:57 ` [PATCH 1/3] git-config.adoc: fix paragraph break Derrick Stolee via GitGitGadget
2026-06-08 13:57 ` [PATCH 2/3] config: add GIT_CONFIG_INCLUDES Derrick Stolee via GitGitGadget
@ 2026-06-08 13:57 ` Derrick Stolee via GitGitGadget
2026-06-08 22:51 ` [PATCH 0/3] config: allow disabling config includes Jeff King
3 siblings, 0 replies; 8+ messages in thread
From: Derrick Stolee via GitGitGadget @ 2026-06-08 13:57 UTC (permalink / raw)
To: git; +Cc: gitster, Derrick Stolee, Derrick Stolee
From: Derrick Stolee <stolee@gmail.com>
The previous change added a GIT_CONFIG_INCLUDES=0 override in the
environment, similar to GIT_ADVICE=0. Follow the same model as
--no-advice to add a --no-includes option to the top-level Git options.
Signed-off-by: Derrick Stolee <stolee@gmail.com>
---
Documentation/git.adoc | 6 +++++-
git.c | 6 +++++-
t/t1305-config-include.sh | 8 ++++++--
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/Documentation/git.adoc b/Documentation/git.adoc
index 8a5cdd3b3d..f220427930 100644
--- a/Documentation/git.adoc
+++ b/Documentation/git.adoc
@@ -12,7 +12,7 @@ SYNOPSIS
'git' [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-lazy-fetch]
- [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]
+ [--no-optional-locks] [--no-advice] [--no-includes] [--bare] [--git-dir=<path>]
[--work-tree=<path>] [--namespace=<name>] [--config-env=<name>=<envvar>]
<command> [<args>]
@@ -194,6 +194,10 @@ If you just want to run git as if it was started in `<path>` then use
--no-advice::
Disable all advice hints from being printed.
+--no-includes::
+ Disable all `include.path` and `includeIf.*` config directives.
+ See linkgit:git-config[1] for more information.
+
--literal-pathspecs::
Treat pathspecs literally (i.e. no globbing, no pathspec magic).
This is equivalent to setting the `GIT_LITERAL_PATHSPECS` environment
diff --git a/git.c b/git.c
index 36f08891ef..52cfbf0e23 100644
--- a/git.c
+++ b/git.c
@@ -40,7 +40,7 @@ const char git_usage_string[] =
N_("git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-lazy-fetch]\n"
- " [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n"
+ " [--no-optional-locks] [--no-advice] [--no-includes] [--bare] [--git-dir=<path>]\n"
" [--work-tree=<path>] [--namespace=<name>] [--config-env=<name>=<envvar>]\n"
" <command> [<args>]");
@@ -354,6 +354,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
setenv(GIT_ADVICE_ENVIRONMENT, "0", 1);
if (envchanged)
*envchanged = 1;
+ } else if (!strcmp(cmd, "--no-includes")) {
+ setenv(CONFIG_INCLUDES_ENVIRONMENT, "0", 1);
+ if (envchanged)
+ *envchanged = 1;
} else {
fprintf(stderr, _("unknown option: %s\n"), cmd);
usage(git_usage_string);
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 270e4b89ab..b636e5ae7b 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -409,8 +409,11 @@ test_expect_success 'GIT_CONFIG_INCLUDES=0 disables include.path and includeIf'
git config get foo.baz &&
test_must_fail env GIT_CONFIG_INCLUDES=0 git config get foo.bar &&
test_must_fail env GIT_CONFIG_INCLUDES=0 git config get foo.baz &&
+ test_must_fail git --no-includes config get foo.bar &&
+ test_must_fail git --no-includes config get foo.baz &&
git config get --includes foo.bar &&
- test_must_fail env GIT_CONFIG_INCLUDES=0 git config get --includes foo.bar
+ test_must_fail env GIT_CONFIG_INCLUDES=0 git config get --includes foo.bar &&
+ test_must_fail git --no-includes config get --includes foo.bar
)
'
@@ -423,7 +426,8 @@ test_expect_success 'GIT_CONFIG_INCLUDES=0 blocks included alias override' '
git config set include.path config.inc &&
git config set -f .git/config.inc alias.test status &&
git test &&
- test_must_fail env GIT_CONFIG_INCLUDES=0 git test
+ test_must_fail env GIT_CONFIG_INCLUDES=0 git test &&
+ test_must_fail git --no-includes test
)
'
--
gitgitgadget
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 0/3] config: allow disabling config includes
2026-06-08 13:57 [PATCH 0/3] config: allow disabling config includes Derrick Stolee via GitGitGadget
` (2 preceding siblings ...)
2026-06-08 13:57 ` [PATCH 3/3] git: add --no-includes top-level option Derrick Stolee via GitGitGadget
@ 2026-06-08 22:51 ` Jeff King
3 siblings, 0 replies; 8+ messages in thread
From: Jeff King @ 2026-06-08 22:51 UTC (permalink / raw)
To: Derrick Stolee via GitGitGadget; +Cc: git, gitster, Derrick Stolee
On Mon, Jun 08, 2026 at 01:57:03PM +0000, Derrick Stolee via GitGitGadget wrote:
> This series introduces a new way to ignore config include directives via two
> mechanisms:
>
> * GIT_CONFIG_INCLUDES=0 in the environment.
> * git --no-includes ... in the command line.
>
> My motivation is from a tricky situation where users want to do the risky
> thing and include a repo-tracked file for sharing aliases and other
> recommended config. They are then struggling in a later build step that is
> running Git commands (under a tool we don't control and can't change) that
> then cause filesystem accesses outside of the build system's sandbox.
I'm not opposed to global control of includes, but this is just one way
in which config can escape the sandbox. They can always point to files
(e.g., core.attributesFile) or even commands that totally leave the
sandbox (e.g., ext diff or textconv commands). Fundamentally git config
is equivalent to arbitrary code execution, so pointing an include at a
repo-tracked file carries the risk of confusion both malicious and
accidental.
So I dunno. From the described motivation, this feels like a band-aid
that fixes only one narrow instance of a greater problem.
The notion of enabling/disabling includes per-command is itself a
flexible building block. So it's possible that it has other uses in
general. But it's also a fairly broad hammer that covers more than your
use case. If you're planning to use "git --no-includes" in some script,
then it breaks the config of anybody who uses includes in their
user-level ~/.gitconfig file.
So you may need some more directed limiting.
> One thing I do worry about is whether or not this would cause a significant
> break in behavior, or if this is a relatively safe thing to allow.
Yeah. Consider something like:
$ cat ~/.gitconfig
[user]
name = My Name
email = me@personal.example.com
[includeIf "gitdir:/path/to/work/stuff"]
path = .gitconfig-work
$ cat ~/.gitconfig-work
[user]
email = me@work.example.com
Using "git --no-include" will silently use the wrong user.email value.
That's OK if the user is asking for it, but if you are planning to
sprinkle "--no-include" inside scripts, that's likely to cause
confusion.
-Peff
^ permalink raw reply [flat|nested] 8+ messages in thread