submodule: allow runtime enabling extensions.submodulePathConfig

Add a new config `init.defaultSubmodulePathConfig` which allows
enabling `extensions.submodulePathConfig` for new submodules by
default (those created via git init or clone).

Important: setting init.defaultSubmodulePathConfig = true does
not globally enable `extensions.submodulePathConfig`. Existing
repositories will still have the extension disabled and will
require migration (for example via git submodule--helper command
added in the next commit).

Suggested-by: Patrick Steinhardt <ps@pks.im>
Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Adrian Ratiu 2026-01-08 01:01:39 +02:00 committed by Junio C Hamano
parent 7ad97f4bea
commit 4cf8c114e3
4 changed files with 145 additions and 0 deletions

View File

@ -95,6 +95,10 @@ Git will error out if a module does not have a corresponding
Existing (pre-extension) submodules need to be migrated by adding the missing
config entries. This is done manually for now, e.g. for each submodule:
`git config submodule.<name>.gitdir .git/modules/<name>`.
+
The extension can be enabled automatically for new repositories by setting
`init.defaultSubmodulePathConfig` to `true`, for example by running
`git config --global init.defaultSubmodulePathConfig true`.
worktreeConfig:::
If enabled, then worktrees will load config settings from the

View File

@ -18,3 +18,9 @@ endif::[]
See `--ref-format=` in linkgit:git-init[1]. Both the command line
option and the `GIT_DEFAULT_REF_FORMAT` environment variable take
precedence over this config.
init.defaultSubmodulePathConfig::
A boolean that specifies if `git init` and `git clone` should
automatically set `extensions.submodulePathConfig` to `true`. This
allows all new repositories to automatically use the submodule path
extension. Defaults to `false` when unset.

10
setup.c
View File

@ -2228,6 +2228,7 @@ void initialize_repository_version(int hash_algo,
{
struct strbuf repo_version = STRBUF_INIT;
int target_version = GIT_REPO_VERSION;
int default_submodule_path_config = 0;
/*
* Note that we initialize the repository version to 1 when the ref
@ -2266,6 +2267,15 @@ void initialize_repository_version(int hash_algo,
clear_repository_format(&repo_fmt);
}
repo_config_get_bool(the_repository, "init.defaultSubmodulePathConfig",
&default_submodule_path_config);
if (default_submodule_path_config) {
/* extensions.submodulepathconfig requires at least version 1 */
if (target_version == 0)
target_version = 1;
repo_config_set(the_repository, "extensions.submodulepathconfig", "true");
}
strbuf_addf(&repo_version, "%d", target_version);
repo_config_set(the_repository, "core.repositoryformatversion", repo_version.buf);

View File

@ -157,4 +157,129 @@ test_expect_success 'fetch mixed submodule changes and verify updates' '
)
'
test_expect_success '`git init` respects init.defaultSubmodulePathConfig' '
git config --global init.defaultSubmodulePathConfig true &&
git init repo-init &&
git -C repo-init config extensions.submodulePathConfig > actual &&
echo true > expect &&
test_cmp expect actual &&
# create a submodule and check gitdir
(
cd repo-init &&
git init -b main sub &&
test_commit -C sub sub-initial &&
git submodule add ./sub sub &&
git config submodule.sub.gitdir > actual &&
echo ".git/modules/sub" > expect &&
test_cmp expect actual
) &&
git config --global --unset init.defaultSubmodulePathConfig
'
test_expect_success '`git init` does not set extension by default' '
git init upstream &&
test_commit -C upstream initial &&
test_must_fail git -C upstream config extensions.submodulePathConfig &&
# create a pair of submodules and check gitdir is not created
git init -b main sub &&
test_commit -C sub sub-initial &&
(
cd upstream &&
git submodule add ../sub sub1 &&
test_path_is_dir .git/modules/sub1 &&
test_must_fail git config submodule.sub1.gitdir &&
git submodule add ../sub sub2 &&
test_path_is_dir .git/modules/sub2 &&
test_must_fail git config submodule.sub2.gitdir &&
git commit -m "Add submodules"
)
'
test_expect_success '`git clone` does not set extension by default' '
test_when_finished "rm -rf repo-clone-no-ext" &&
git clone upstream repo-clone-no-ext &&
(
cd repo-clone-no-ext &&
test_must_fail git config extensions.submodulePathConfig &&
test_path_is_missing .git/modules/sub1 &&
test_path_is_missing .git/modules/sub2 &&
# create a submodule and check gitdir is not created
git submodule add ../sub sub3 &&
test_must_fail git config submodule.sub3.gitdir
)
'
test_expect_success '`git clone --recurse-submodules` does not set extension by default' '
test_when_finished "rm -rf repo-clone-no-ext" &&
git clone --recurse-submodules upstream repo-clone-no-ext &&
(
cd repo-clone-no-ext &&
# verify that that submodules do not have gitdir set
test_must_fail git config extensions.submodulePathConfig &&
test_path_is_dir .git/modules/sub1 &&
test_must_fail git config submodule.sub1.gitdir &&
test_path_is_dir .git/modules/sub2 &&
test_must_fail git config submodule.sub2.gitdir &&
# create another submodule and check that gitdir is not created
git submodule add ../sub sub3 &&
test_path_is_dir .git/modules/sub3 &&
test_must_fail git config submodule.sub3.gitdir
)
'
test_expect_success '`git clone` respects init.defaultSubmodulePathConfig' '
test_when_finished "rm -rf repo-clone" &&
git config --global init.defaultSubmodulePathConfig true &&
git clone upstream repo-clone &&
(
cd repo-clone &&
# verify new repo extension is inherited from global config
git config extensions.submodulePathConfig > actual &&
echo true > expect &&
test_cmp expect actual &&
# new submodule has a gitdir config
git submodule add ../sub sub &&
test_path_is_dir .git/modules/sub &&
git config submodule.sub.gitdir > actual &&
echo ".git/modules/sub" > expect &&
test_cmp expect actual
) &&
git config --global --unset init.defaultSubmodulePathConfig
'
test_expect_success '`git clone --recurse-submodules` respects init.defaultSubmodulePathConfig' '
test_when_finished "rm -rf repo-clone-recursive" &&
git config --global init.defaultSubmodulePathConfig true &&
git clone --recurse-submodules upstream repo-clone-recursive &&
(
cd repo-clone-recursive &&
# verify new repo extension is inherited from global config
git config extensions.submodulePathConfig > actual &&
echo true > expect &&
test_cmp expect actual &&
# previous submodules should exist
git config submodule.sub1.gitdir &&
git config submodule.sub2.gitdir &&
test_path_is_dir .git/modules/sub1 &&
test_path_is_dir .git/modules/sub2 &&
# create another submodule and check that gitdir is created
git submodule add ../sub new-sub &&
test_path_is_dir .git/modules/new-sub &&
git config submodule.new-sub.gitdir > actual &&
echo ".git/modules/new-sub" > expect &&
test_cmp expect actual
) &&
git config --global --unset init.defaultSubmodulePathConfig
'
test_done