]> git.ipfire.org Git - thirdparty/git.git/commitdiff
submodule: allow runtime enabling extensions.submodulePathConfig
authorAdrian Ratiu <adrian.ratiu@collabora.com>
Wed, 7 Jan 2026 23:01:39 +0000 (01:01 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 8 Jan 2026 02:05:15 +0000 (11:05 +0900)
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>
Documentation/config/extensions.adoc
Documentation/config/init.adoc
setup.c
t/t7425-submodule-gitdir-path-extension.sh

index f4f57c91141ccffde0b4d690575855bfdf671b42..e8d9d9a19a5fb62cc7b9ee15a9878e636016380b 100644 (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
index e45b2a812151dc45755b650ecd0839f4029c5c2a..7b4abdaf8ba29b8d61c8a8cf1141a60727efcccc 100644 (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.
diff --git a/setup.c b/setup.c
index 207fa36e100b61e0a5f35d04f2e75d39ecf76457..3f91a4aaec174bd955e3c035f1741b0278c73d1a 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -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);
 
index 453183e27c95a29953c86963a260b0ee9ede1cad..6cb844e809e4d63a5cc0adcfd697695f210727a1 100755 (executable)
@@ -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