Skip to content

Commit fdb4d27

Browse files
committed
Merge branch 'jl/submodule-add-by-name'
If you remove a submodule, in order to keep the repository so that "git checkout" to an older commit in the superproject history can resurrect the submodule, the real repository will stay in $GIT_DIR of the superproject. A later "git submodule add $path" to add a different submodule at the same path will fail. Diagnose this case a bit better, and if the user really wants to add an unrelated submodule at the same path, give the "--name" option to give it a place in $GIT_DIR of the superproject that does not conflict with the original submodule. * jl/submodule-add-by-name: submodule add: Fail when .git/modules/<name> already exists unless forced Teach "git submodule add" the --name option
2 parents d21240f + 4b7c286 commit fdb4d27

File tree

5 files changed

+121
-14
lines changed

5 files changed

+121
-14
lines changed

Documentation/git-submodule.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-submodule - Initialize, update or inspect submodules
99
SYNOPSIS
1010
--------
1111
[verse]
12-
'git submodule' [--quiet] add [-b branch] [-f|--force]
12+
'git submodule' [--quiet] add [-b branch] [-f|--force] [--name <name>]
1313
[--reference <repository>] [--] <repository> [<path>]
1414
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
1515
'git submodule' [--quiet] init [--] [<path>...]
@@ -265,6 +265,11 @@ OPTIONS
265265
Initialize all submodules for which "git submodule init" has not been
266266
called so far before updating.
267267

268+
--name::
269+
This option is only valid for the add command. It sets the submodule's
270+
name to the given string instead of defaulting to its path. The name
271+
must be valid as a directory name and may not end with a '/'.
272+
268273
--reference <repository>::
269274
This option is only valid for add and update commands. These
270275
commands sometimes need to clone a remote repository. In this case,

Documentation/gitmodules.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ working tree, is a text file with a syntax matching the requirements
1818
of linkgit:git-config[1].
1919

2020
The file contains one subsection per submodule, and the subsection value
21-
is the name of the submodule. Each submodule section also contains the
21+
is the name of the submodule. The name is set to the path where the
22+
submodule has been added unless it was customized with the '--name'
23+
option of 'git submodule add'. Each submodule section also contains the
2224
following required keys:
2325

2426
submodule.<name>.path::

git-submodule.sh

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Copyright (c) 2007 Lars Hjemli
66

77
dashless=$(basename "$0" | sed -e 's/-/ /')
8-
USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
8+
USAGE="[--quiet] add [-b branch] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
99
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
1010
or: $dashless [--quiet] init [--] [<path>...]
1111
or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
@@ -29,6 +29,7 @@ files=
2929
nofetch=
3030
update=
3131
prefix=
32+
custom_name=
3233

3334
# The function takes at most 2 arguments. The first argument is the
3435
# URL that navigates to the submodule origin repo. When relative, this URL
@@ -179,8 +180,9 @@ module_name()
179180
module_clone()
180181
{
181182
sm_path=$1
182-
url=$2
183-
reference="$3"
183+
name=$2
184+
url=$3
185+
reference="$4"
184186
quiet=
185187
if test -n "$GIT_QUIET"
186188
then
@@ -189,8 +191,6 @@ module_clone()
189191

190192
gitdir=
191193
gitdir_base=
192-
name=$(module_name "$sm_path" 2>/dev/null)
193-
test -n "$name" || name="$sm_path"
194194
base_name=$(dirname "$name")
195195

196196
gitdir=$(git rev-parse --git-dir)
@@ -272,6 +272,11 @@ cmd_add()
272272
reference="$1"
273273
shift
274274
;;
275+
--name)
276+
case "$2" in '') usage ;; esac
277+
custom_name=$2
278+
shift
279+
;;
275280
--)
276281
shift
277282
break
@@ -336,6 +341,13 @@ Use -f if you really want to add it." >&2
336341
exit 1
337342
fi
338343

344+
if test -n "$custom_name"
345+
then
346+
sm_name="$custom_name"
347+
else
348+
sm_name="$sm_path"
349+
fi
350+
339351
# perhaps the path exists and is already a git repo, else clone it
340352
if test -e "$sm_path"
341353
then
@@ -347,8 +359,21 @@ Use -f if you really want to add it." >&2
347359
fi
348360

349361
else
350-
351-
module_clone "$sm_path" "$realrepo" "$reference" || exit
362+
if test -d ".git/modules/$sm_name"
363+
then
364+
if test -z "$force"
365+
then
366+
echo >&2 "$(eval_gettext "A git directory for '\$sm_name' is found locally with remote(s):")"
367+
GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^," ", -e s,' (fetch)',, >&2
368+
echo >&2 "$(eval_gettext "If you want to reuse this local git directory instead of cloning again from")"
369+
echo >&2 " $realrepo"
370+
echo >&2 "$(eval_gettext "use the '--force' option. If the local git directory is not the correct repo")"
371+
die "$(eval_gettext "or you are unsure what this means choose another name with the '--name' option.")"
372+
else
373+
echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
374+
fi
375+
fi
376+
module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" || exit
352377
(
353378
clear_local_git_env
354379
cd "$sm_path" &&
@@ -359,13 +384,13 @@ Use -f if you really want to add it." >&2
359384
esac
360385
) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
361386
fi
362-
git config submodule."$sm_path".url "$realrepo"
387+
git config submodule."$sm_name".url "$realrepo"
363388

364389
git add $force "$sm_path" ||
365390
die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
366391

367-
git config -f .gitmodules submodule."$sm_path".path "$sm_path" &&
368-
git config -f .gitmodules submodule."$sm_path".url "$repo" &&
392+
git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
393+
git config -f .gitmodules submodule."$sm_name".url "$repo" &&
369394
git add --force .gitmodules ||
370395
die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
371396
}
@@ -594,7 +619,7 @@ Maybe you want to use 'update --init'?")"
594619

595620
if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
596621
then
597-
module_clone "$sm_path" "$url" "$reference"|| exit
622+
module_clone "$sm_path" "$name" "$url" "$reference" || exit
598623
cloned_modules="$cloned_modules;$name"
599624
subsha1=
600625
else

t/t7400-submodule-basic.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,4 +681,79 @@ test_expect_success 'moving the superproject does not break submodules' '
681681
)
682682
'
683683

684+
test_expect_success 'submodule add --name allows to replace a submodule with another at the same path' '
685+
(
686+
cd addtest2 &&
687+
(
688+
cd repo &&
689+
echo "$submodurl/repo" >expect &&
690+
git config remote.origin.url >actual &&
691+
test_cmp expect actual &&
692+
echo "gitdir: ../.git/modules/repo" >expect &&
693+
test_cmp expect .git
694+
) &&
695+
rm -rf repo &&
696+
git rm repo &&
697+
git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual &&
698+
test ! -s actual &&
699+
echo "gitdir: ../.git/modules/submod" >expect &&
700+
test_cmp expect submod/.git &&
701+
(
702+
cd repo &&
703+
echo "$submodurl/bare.git" >expect &&
704+
git config remote.origin.url >actual &&
705+
test_cmp expect actual &&
706+
echo "gitdir: ../.git/modules/repo_new" >expect &&
707+
test_cmp expect .git
708+
) &&
709+
echo "repo" >expect &&
710+
git config -f .gitmodules submodule.repo.path >actual &&
711+
test_cmp expect actual &&
712+
git config -f .gitmodules submodule.repo_new.path >actual &&
713+
test_cmp expect actual&&
714+
echo "$submodurl/repo" >expect &&
715+
git config -f .gitmodules submodule.repo.url >actual &&
716+
test_cmp expect actual &&
717+
echo "$submodurl/bare.git" >expect &&
718+
git config -f .gitmodules submodule.repo_new.url >actual &&
719+
test_cmp expect actual &&
720+
echo "$submodurl/repo" >expect &&
721+
git config submodule.repo.url >actual &&
722+
test_cmp expect actual &&
723+
echo "$submodurl/bare.git" >expect &&
724+
git config submodule.repo_new.url >actual &&
725+
test_cmp expect actual
726+
)
727+
'
728+
729+
test_expect_success 'submodule add with an existing name fails unless forced' '
730+
(
731+
cd addtest2 &&
732+
rm -rf repo &&
733+
git rm repo &&
734+
test_must_fail git submodule add -q --name repo_new "$submodurl/repo.git" repo &&
735+
test ! -d repo &&
736+
echo "repo" >expect &&
737+
git config -f .gitmodules submodule.repo_new.path >actual &&
738+
test_cmp expect actual&&
739+
echo "$submodurl/bare.git" >expect &&
740+
git config -f .gitmodules submodule.repo_new.url >actual &&
741+
test_cmp expect actual &&
742+
echo "$submodurl/bare.git" >expect &&
743+
git config submodule.repo_new.url >actual &&
744+
test_cmp expect actual &&
745+
git submodule add -f -q --name repo_new "$submodurl/repo.git" repo &&
746+
test -d repo &&
747+
echo "repo" >expect &&
748+
git config -f .gitmodules submodule.repo_new.path >actual &&
749+
test_cmp expect actual&&
750+
echo "$submodurl/repo.git" >expect &&
751+
git config -f .gitmodules submodule.repo_new.url >actual &&
752+
test_cmp expect actual &&
753+
echo "$submodurl/repo.git" >expect &&
754+
git config submodule.repo_new.url >actual &&
755+
test_cmp expect actual
756+
)
757+
'
758+
684759
test_done

t/t7406-submodule-update.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ test_expect_success 'submodule add properly re-creates deeper level submodules'
627627
(cd super &&
628628
git reset --hard master &&
629629
rm -rf deeper/ &&
630-
git submodule add ../submodule deeper/submodule
630+
git submodule add --force ../submodule deeper/submodule
631631
)
632632
'
633633

0 commit comments

Comments
 (0)