diff --git a/Documentation/config/submodule.txt b/Documentation/config/submodule.txt
index d7a63c8c12..7c459cc19e 100644
--- a/Documentation/config/submodule.txt
+++ b/Documentation/config/submodule.txt
@@ -90,3 +90,15 @@ submodule.alternateErrorStrategy::
`ignore`, `info`, `die`. Default is `die`. Note that if set to `ignore`
or `info`, and if there is an error with the computed alternate, the
clone proceeds as if no alternate was specified.
+
+submodule.superprojectGitDir::
+ The relative path from the submodule's worktree to the superproject's
+ gitdir. This config should only be present in projects which are
+ submodules, but is not guaranteed to be present in every submodule. It
+ is set automatically during submodule creation.
++
+ In situations where more than one superproject references the same
+ submodule worktree, the value of this config and the behavior of
+ operations which use it are undefined. To reference a single project
+ from multiple superprojects, it is better to create a worktree of the
+ submodule for each superproject.
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d55f6262e9..d60fcd2c7d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1910,6 +1910,10 @@ static int module_clone(int argc, const char **argv, const char *prefix)
git_config_set_in_file(p, "submodule.alternateErrorStrategy",
error_strategy);
+ git_config_set_in_file(p, "submodule.superprojectGitdir",
+ relative_path(absolute_path(get_git_dir()),
+ path, &sb));
+
free(sm_alternate);
free(error_strategy);
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index f5dc051a6e..e45f42588f 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -108,14 +108,18 @@ test_expect_success 'setup - repository to add submodules to' '
submodurl=$(pwd -P)
inspect() {
- dir=$1 &&
-
- git -C "$dir" for-each-ref --format='%(refname)' 'refs/heads/*' >heads &&
- { git -C "$dir" symbolic-ref HEAD || :; } >head &&
- git -C "$dir" rev-parse HEAD >head-sha1 &&
- git -C "$dir" update-index --refresh &&
- git -C "$dir" diff-files --exit-code &&
- git -C "$dir" clean -n -d -x >untracked
+ sub_dir=$1 &&
+ super_dir=$2 &&
+
+ git -C "$sub_dir" for-each-ref --format='%(refname)' 'refs/heads/*' >heads &&
+ { git -C "$sub_dir" symbolic-ref HEAD || :; } >head &&
+ git -C "$sub_dir" rev-parse HEAD >head-sha1 &&
+ git -C "$sub_dir" update-index --refresh &&
+ git -C "$sub_dir" diff-files --exit-code &&
+ cached_super_dir="$(git -C "$sub_dir" config --get submodule.superprojectGitDir)" &&
+ [ "$(git -C "$super_dir" rev-parse --absolute-git-dir)" \
+ -ef "$sub_dir/$cached_super_dir" ] &&
+ git -C "$sub_dir" clean -n -d -x >untracked
}
@@ -139,7 +143,7 @@ test_expect_success 'submodule add' '
) &&
rm -f heads head untracked &&
- inspect addtest/submod &&
+ inspect addtest/submod addtest &&
test_cmp expect heads &&
test_cmp expect head &&
test_must_be_empty untracked
@@ -230,7 +234,7 @@ test_expect_success 'submodule add --branch' '
) &&
rm -f heads head untracked &&
- inspect addtest/submod-branch &&
+ inspect addtest/submod-branch addtest &&
test_cmp expect-heads heads &&
test_cmp expect-head head &&
test_must_be_empty untracked
@@ -246,7 +250,7 @@ test_expect_success 'submodule add with ./ in path' '
) &&
rm -f heads head untracked &&
- inspect addtest/dotsubmod/frotz &&
+ inspect addtest/dotsubmod/frotz addtest &&
test_cmp expect heads &&
test_cmp expect head &&
test_must_be_empty untracked
@@ -262,7 +266,7 @@ test_expect_success 'submodule add with /././ in path' '
) &&
rm -f heads head untracked &&
- inspect addtest/dotslashdotsubmod/frotz &&
+ inspect addtest/dotslashdotsubmod/frotz addtest &&
test_cmp expect heads &&
test_cmp expect head &&
test_must_be_empty untracked
@@ -278,7 +282,7 @@ test_expect_success 'submodule add with // in path' '
) &&
rm -f heads head untracked &&
- inspect addtest/slashslashsubmod/frotz &&
+ inspect addtest/slashslashsubmod/frotz addtest &&
test_cmp expect heads &&
test_cmp expect head &&
test_must_be_empty untracked
@@ -294,7 +298,7 @@ test_expect_success 'submodule add with /.. in path' '
) &&
rm -f heads head untracked &&
- inspect addtest/realsubmod &&
+ inspect addtest/realsubmod addtest &&
test_cmp expect heads &&
test_cmp expect head &&
test_must_be_empty untracked
@@ -310,7 +314,7 @@ test_expect_success 'submodule add with ./, /.. and // in path' '
) &&
rm -f heads head untracked &&
- inspect addtest/realsubmod2 &&
+ inspect addtest/realsubmod2 addtest &&
test_cmp expect heads &&
test_cmp expect head &&
test_must_be_empty untracked
@@ -341,7 +345,7 @@ test_expect_success 'submodule add in subdirectory' '
) &&
rm -f heads head untracked &&
- inspect addtest/realsubmod3 &&
+ inspect addtest/realsubmod3 addtest &&
test_cmp expect heads &&
test_cmp expect head &&
test_must_be_empty untracked
@@ -482,7 +486,7 @@ test_expect_success 'update should work when path is an empty dir' '
git submodule update -q >update.out &&
test_must_be_empty update.out &&
- inspect init &&
+ inspect init . &&
test_cmp expect head-sha1
'
@@ -541,7 +545,7 @@ test_expect_success 'update should checkout rev1' '
echo "$rev1" >expect &&
git submodule update init &&
- inspect init &&
+ inspect init . &&
test_cmp expect head-sha1
'
--
2.32.0.272.g935e593368-goog