mirror of
https://github.com/git/git.git
synced 2025-04-02 02:30:54 +00:00
Merge branch 'jl/submodule-deinit'
There was no Porcelain way to say "I no longer am interested in this submodule", once you express your interest in a submodule with "submodule init". "submodule deinit" is the way to do so. * jl/submodule-deinit: submodule: add 'deinit' command
This commit is contained in:
commit
b03b41e24c
@ -149,6 +149,10 @@ files that aren't ignored are present in the submodules work tree.
|
|||||||
Ignored files are deemed expendable and won't stop a submodule's work
|
Ignored files are deemed expendable and won't stop a submodule's work
|
||||||
tree from being removed.
|
tree from being removed.
|
||||||
|
|
||||||
|
If you only want to remove the local checkout of a submodule from your
|
||||||
|
work tree without committing the removal,
|
||||||
|
use linkgit:git-submodule[1] `deinit` instead.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
`git rm Documentation/\*.txt`::
|
`git rm Documentation/\*.txt`::
|
||||||
|
@ -13,6 +13,7 @@ SYNOPSIS
|
|||||||
[--reference <repository>] [--] <repository> [<path>]
|
[--reference <repository>] [--] <repository> [<path>]
|
||||||
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
|
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
|
||||||
'git submodule' [--quiet] init [--] [<path>...]
|
'git submodule' [--quiet] init [--] [<path>...]
|
||||||
|
'git submodule' [--quiet] deinit [-f|--force] [--] <path>...
|
||||||
'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
|
'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
|
||||||
[-f|--force] [--rebase] [--reference <repository>]
|
[-f|--force] [--rebase] [--reference <repository>]
|
||||||
[--merge] [--recursive] [--] [<path>...]
|
[--merge] [--recursive] [--] [<path>...]
|
||||||
@ -135,6 +136,19 @@ init::
|
|||||||
the explicit 'init' step if you do not intend to customize
|
the explicit 'init' step if you do not intend to customize
|
||||||
any submodule locations.
|
any submodule locations.
|
||||||
|
|
||||||
|
deinit::
|
||||||
|
Unregister the given submodules, i.e. remove the whole
|
||||||
|
`submodule.$name` section from .git/config together with their work
|
||||||
|
tree. Further calls to `git submodule update`, `git submodule foreach`
|
||||||
|
and `git submodule sync` will skip any unregistered submodules until
|
||||||
|
they are initialized again, so use this command if you don't want to
|
||||||
|
have a local checkout of the submodule in your work tree anymore. If
|
||||||
|
you really want to remove a submodule from the repository and commit
|
||||||
|
that use linkgit:git-rm[1] instead.
|
||||||
|
+
|
||||||
|
If `--force` is specified, the submodule's work tree will be removed even if
|
||||||
|
it contains local modifications.
|
||||||
|
|
||||||
update::
|
update::
|
||||||
Update the registered submodules, i.e. clone missing submodules and
|
Update the registered submodules, i.e. clone missing submodules and
|
||||||
checkout the commit specified in the index of the containing repository.
|
checkout the commit specified in the index of the containing repository.
|
||||||
@ -214,8 +228,10 @@ OPTIONS
|
|||||||
|
|
||||||
-f::
|
-f::
|
||||||
--force::
|
--force::
|
||||||
This option is only valid for add and update commands.
|
This option is only valid for add, deinit and update commands.
|
||||||
When running add, allow adding an otherwise ignored submodule path.
|
When running add, allow adding an otherwise ignored submodule path.
|
||||||
|
When running deinit the submodule work trees will be removed even if
|
||||||
|
they contain local changes.
|
||||||
When running update, throw away local changes in submodules when
|
When running update, throw away local changes in submodules when
|
||||||
switching to a different commit; and always run a checkout operation
|
switching to a different commit; and always run a checkout operation
|
||||||
in the submodule, even if the commit listed in the index of the
|
in the submodule, even if the commit listed in the index of the
|
||||||
|
@ -2419,7 +2419,7 @@ _git_submodule ()
|
|||||||
{
|
{
|
||||||
__git_has_doubledash && return
|
__git_has_doubledash && return
|
||||||
|
|
||||||
local subcommands="add status init update summary foreach sync"
|
local subcommands="add status init deinit update summary foreach sync"
|
||||||
if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
|
if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
--*)
|
--*)
|
||||||
|
@ -8,6 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
|
|||||||
USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
|
USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
|
||||||
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
|
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
|
||||||
or: $dashless [--quiet] init [--] [<path>...]
|
or: $dashless [--quiet] init [--] [<path>...]
|
||||||
|
or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
|
||||||
or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
|
or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
|
||||||
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
|
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
|
||||||
or: $dashless [--quiet] foreach [--recursive] <command>
|
or: $dashless [--quiet] foreach [--recursive] <command>
|
||||||
@ -546,6 +547,80 @@ cmd_init()
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Unregister submodules from .git/config and remove their work tree
|
||||||
|
#
|
||||||
|
# $@ = requested paths (use '.' to deinit all submodules)
|
||||||
|
#
|
||||||
|
cmd_deinit()
|
||||||
|
{
|
||||||
|
# parse $args after "submodule ... deinit".
|
||||||
|
while test $# -ne 0
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
-f|--force)
|
||||||
|
force=$1
|
||||||
|
;;
|
||||||
|
-q|--quiet)
|
||||||
|
GIT_QUIET=1
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test $# = 0
|
||||||
|
then
|
||||||
|
die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
module_list "$@" |
|
||||||
|
while read mode sha1 stage sm_path
|
||||||
|
do
|
||||||
|
die_if_unmatched "$mode"
|
||||||
|
name=$(module_name "$sm_path") || exit
|
||||||
|
|
||||||
|
# Remove the submodule work tree (unless the user already did it)
|
||||||
|
if test -d "$sm_path"
|
||||||
|
then
|
||||||
|
# Protect submodules containing a .git directory
|
||||||
|
if test -d "$sm_path/.git"
|
||||||
|
then
|
||||||
|
echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")"
|
||||||
|
die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$force"
|
||||||
|
then
|
||||||
|
git rm -n "$sm_path" ||
|
||||||
|
die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
|
||||||
|
fi
|
||||||
|
rm -rf "$sm_path" || say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")"
|
||||||
|
|
||||||
|
# Remove the .git/config entries (unless the user already did it)
|
||||||
|
if test -n "$(git config --get-regexp submodule."$name\.")"
|
||||||
|
then
|
||||||
|
# Remove the whole section so we have a clean state when
|
||||||
|
# the user later decides to init this submodule again
|
||||||
|
url=$(git config submodule."$name".url)
|
||||||
|
git config --remove-section submodule."$name" 2>/dev/null &&
|
||||||
|
say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$sm_path'")"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Update each submodule path to correct revision, using clone and checkout as needed
|
# Update each submodule path to correct revision, using clone and checkout as needed
|
||||||
#
|
#
|
||||||
@ -1162,7 +1237,7 @@ cmd_sync()
|
|||||||
while test $# != 0 && test -z "$command"
|
while test $# != 0 && test -z "$command"
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
add | foreach | init | update | status | summary | sync)
|
add | foreach | init | deinit | update | status | summary | sync)
|
||||||
command=$1
|
command=$1
|
||||||
;;
|
;;
|
||||||
-q|--quiet)
|
-q|--quiet)
|
||||||
|
@ -757,4 +757,104 @@ test_expect_success 'submodule add with an existing name fails unless forced' '
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'set up a second submodule' '
|
||||||
|
git submodule add ./init2 example2 &&
|
||||||
|
git commit -m "submodule example2 added"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit should remove the whole submodule section from .git/config' '
|
||||||
|
git config submodule.example.foo bar &&
|
||||||
|
git config submodule.example2.frotz nitfol &&
|
||||||
|
git submodule deinit init &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
test -n "$(git config --get-regexp "submodule\.example2\.")" &&
|
||||||
|
test -f example2/.git &&
|
||||||
|
rmdir init
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit . deinits all initialized submodules' '
|
||||||
|
git submodule update --init &&
|
||||||
|
git config submodule.example.foo bar &&
|
||||||
|
git config submodule.example2.frotz nitfol &&
|
||||||
|
test_must_fail git submodule deinit &&
|
||||||
|
git submodule deinit . &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example2\.")" &&
|
||||||
|
rmdir init example2
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit deinits a submodule when its work tree is missing or empty' '
|
||||||
|
git submodule update --init &&
|
||||||
|
rm -rf init example2/* example2/.git &&
|
||||||
|
git submodule deinit init example2 &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example2\.")" &&
|
||||||
|
rmdir init
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit fails when the submodule contains modifications unless forced' '
|
||||||
|
git submodule update --init &&
|
||||||
|
echo X >>init/s &&
|
||||||
|
test_must_fail git submodule deinit init &&
|
||||||
|
test -n "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
test -f example2/.git &&
|
||||||
|
git submodule deinit -f init &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
rmdir init
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit fails when the submodule contains untracked files unless forced' '
|
||||||
|
git submodule update --init &&
|
||||||
|
echo X >>init/untracked &&
|
||||||
|
test_must_fail git submodule deinit init &&
|
||||||
|
test -n "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
test -f example2/.git &&
|
||||||
|
git submodule deinit -f init &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
rmdir init
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit fails when the submodule HEAD does not match unless forced' '
|
||||||
|
git submodule update --init &&
|
||||||
|
(
|
||||||
|
cd init &&
|
||||||
|
git checkout HEAD^
|
||||||
|
) &&
|
||||||
|
test_must_fail git submodule deinit init &&
|
||||||
|
test -n "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
test -f example2/.git &&
|
||||||
|
git submodule deinit -f init &&
|
||||||
|
test -z "$(git config --get-regexp "submodule\.example\.")" &&
|
||||||
|
rmdir init
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit is silent when used on an uninitialized submodule' '
|
||||||
|
git submodule update --init &&
|
||||||
|
git submodule deinit init >actual &&
|
||||||
|
test_i18ngrep "Submodule .example. (.*) unregistered for path .init" actual &&
|
||||||
|
git submodule deinit init >actual &&
|
||||||
|
test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
|
||||||
|
git submodule deinit . >actual &&
|
||||||
|
test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
|
||||||
|
test_i18ngrep "Submodule .example2. (.*) unregistered for path .example2" actual &&
|
||||||
|
git submodule deinit . >actual &&
|
||||||
|
test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
|
||||||
|
test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
|
||||||
|
rmdir init example2
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'submodule deinit fails when submodule has a .git directory even when forced' '
|
||||||
|
git submodule update --init &&
|
||||||
|
(
|
||||||
|
cd init &&
|
||||||
|
rm .git &&
|
||||||
|
cp -R ../.git/modules/example .git &&
|
||||||
|
GIT_WORK_TREE=. git config --unset core.worktree
|
||||||
|
) &&
|
||||||
|
test_must_fail git submodule deinit init &&
|
||||||
|
test_must_fail git submodule deinit -f init &&
|
||||||
|
test -d init/.git &&
|
||||||
|
test -n "$(git config --get-regexp "submodule\.example\.")"
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
x
Reference in New Issue
Block a user