diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc index 00545b20542c60..c9b5159501e111 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 <>. GIT_CONFIG_COUNT:: @@ -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/Documentation/git.adoc b/Documentation/git.adoc index 8a5cdd3b3d22c5..f220427930afba 100644 --- a/Documentation/git.adoc +++ b/Documentation/git.adoc @@ -12,7 +12,7 @@ SYNOPSIS 'git' [-v | --version] [-h | --help] [-C ] [-c =] [--exec-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=] + [--no-optional-locks] [--no-advice] [--no-includes] [--bare] [--git-dir=] [--work-tree=] [--namespace=] [--config-env==] [] @@ -194,6 +194,10 @@ If you just want to run git as if it was started in `` 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/config.c b/config.c index a1b92fe083cf43..85edd05672d709 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 9eb97b3869c9b1..2c57ae2533a2c9 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/git.c b/git.c index 36f08891ef5476..52cfbf0e23e2a1 100644 --- a/git.c +++ b/git.c @@ -40,7 +40,7 @@ const char git_usage_string[] = N_("git [-v | --version] [-h | --help] [-C ] [-c =]\n" " [--exec-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=]\n" + " [--no-optional-locks] [--no-advice] [--no-includes] [--bare] [--git-dir=]\n" " [--work-tree=] [--namespace=] [--config-env==]\n" " []"); @@ -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 f3892578e4ff86..b636e5ae7b1dc2 100755 --- a/t/t1305-config-include.sh +++ b/t/t1305-config-include.sh @@ -396,4 +396,39 @@ 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 && + 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 git --no-includes 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_must_fail git --no-includes test + ) +' + test_done