git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2] submodule: add 'deinit' command

From
Jens Lehmann <jens.lehmann@web.de>
Date
Dec 4, 2012, 21:48 UTC
Message-ID
<50BE6FB9.70301@web.de>
In-Reply-To
<7vhao31s9e.fsf@alter.siamese.dyndns.org>

With "git submodule init" the user is able to tell git he cares about one or more submodules and wants to have it populated on the next call to "git submodule update". But currently there is no easy way he could tell git he does not care about a submodule anymore and wants to get rid of his local work tree (except he knows a lot about submodule internals and removes the "submodule.$name.url" setting from .git/config himself).

Help those users by providing a 'deinit' command. This removes the whole submodule.<name> section from .git/config either for the given submodule(s) or for all those which have been initialized if none were given. Complain only when for a submodule given on the command line the url setting can't be found in .git/config.

Add tests and link the man pages of "git submodule deinit" and "git rm" to assist the user in deciding whether removing or unregistering the submodule is the right thing to do for him.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
---
Am 03.12.2012 08:58, schrieb Junio C Hamano:
Show 27 quoted lines
> Jens Lehmann <Jens.Lehmann@web.de> writes:
> 
>> Maybe the principle of least surprise is better followed when we
>> nuke the whole section, as it might surprise the user more to have
>> a setting resurrected he customized in the last life cycle of the
>> submodule than seeing that after an deinit followed by an init all
>> former customizations are consistently gone. So I tend to think now
>> that removing the whole section would be the better solution here.
> 
> I tend to agree; I suspect that a "deinit" would be mostly done
> either to
> 
>  (1) correct mistakes the user made during a recent "init" and
>      perhaps "sync"; or
> 
>  (2) tell Git that the user has finished woing with this particular
>      submodule and does not intend to use it for quite a while.
> 
> For both (1) and (2), I think it would be easier to users if we gave
> them a clean slate, the same state as the one the user who never had
> ran "init" on it would be in.  A user in situation (1) is asking for
> a clean slate, and a user in situation (2) is better served if he
> does not have to worry about leftover entries in $GIT_DIR/config he
> has long forgotten from many months ago (during which time the way
> the project uses the particular submodule may well have changed)
> giving non-standard experience different from what other project
> participants would get.
Changes in v2:
- Remove the whole submodule section instead of only removing the
  "url" setting and explain why we do that in a comment
- Reworded commit message and git-submodule.txt to reflect that
- Extend the test to check that a custom settings are removed
 Documentation/git-rm.txt        |  4 ++++
 Documentation/git-submodule.txt | 12 ++++++++++
 git-submodule.sh                | 52 ++++++++++++++++++++++++++++++++++++++++-
 t/t7400-submodule-basic.sh      | 12 ++++++++++
 4 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt
index 262436b..ec42bf5 100644
--- a/Documentation/git-rm.txt
+++ b/Documentation/git-rm.txt
@@ -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
 tree from being removed.

+If you only want to remove the local checkout of a submodule from your
+work tree without committing that use `git submodule deinit` instead
+(see linkgit:git-submodule[1]).
+
 EXAMPLES
 --------
 `git rm Documentation/\*.txt`::
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index b1de3ba..08b55a7 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -13,6 +13,7 @@ SYNOPSIS
 	      [--reference <repository>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
+'git submodule' [--quiet] deinit [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
 	      [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
@@ -134,6 +135,17 @@ init::
 	the explicit 'init' step if you do not intend to customize
 	any submodule locations.

+deinit::
+	Unregister the submodules, i.e. remove the whole `submodule.$name`
+	section from .git/config. 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 (but note that this command
+	does not remove the submodule work tree). If you really want to
+	remove a submodule from the repository and commit that use
+	linkgit:git-rm[1] instead.
+
 update::
 	Update the registered submodules, i.e. clone missing submodules and
 	checkout the commit specified in the index of the containing repository.
diff --git a/git-submodule.sh b/git-submodule.sh
index 2365149..3f558ed 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -8,6 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
+   or: $dashless [--quiet] deinit [--] [<path>...]
    or: $dashless [--quiet] update [--init] [-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] foreach [--recursive] <command>
@@ -516,6 +517,55 @@ cmd_init()
 }

 #
+# Unregister submodules from .git/config
+#
+# $@ = requested paths (default to all)
+#
+cmd_deinit()
+{
+	# parse $args after "submodule ... init".
+	while test $# -ne 0
+	do
+		case "$1" in
+		-q|--quiet)
+			GIT_QUIET=1
+			;;
+		--)
+			shift
+			break
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
+	module_list "$@" |
+	while read mode sha1 stage sm_path
+	do
+		die_if_unmatched "$mode"
+		name=$(module_name "$sm_path") || exit
+		url=$(git config submodule."$name".url)
+		if test -z "$url"
+		then
+			# Only mention uninitialized submodules when its
+			# path have been specified
+			test "$#" != "0" &&
+			say "$(eval_gettext "No url found for submodule path '\$sm_path' in .git/config")"
+			continue
+		fi
+		# Remove the whole section so we have a clean state when the user
+		# later decides to init this submodule again
+		git config --remove-section submodule."$name" &&
+		say "$(eval_gettext "Submodule '\$name' (\$url) unregistered")"
+	done
+}
+
+#
 # Update each submodule path to correct revision, using clone and checkout as needed
 #
 # $@ = requested paths (default to all)
@@ -1108,7 +1158,7 @@ cmd_sync()
 while test $# != 0 && test -z "$command"
 do
 	case "$1" in
-	add | foreach | init | update | status | summary | sync)
+	add | foreach | init | deinit | update | status | summary | sync)
 		command=$1
 		;;
 	-q|--quiet)
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index de7d453..ee4f0ab 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -756,4 +756,16 @@ test_expect_success 'submodule add with an existing name fails unless forced' '
 	)
 '

+test_expect_success 'submodule deinit should remove the whole submodule section from .git/config' '
+	git config submodule.example.foo bar &&
+	git submodule deinit &&
+	test -z "$(git config submodule.example.url)" &&
+	test -z "$(git config submodule.example.foo)"
+'
+
+test_expect_success 'submodule deinit complains only when explicitly used on an uninitialized submodule' '
+	git submodule deinit &&
+	test_must_fail git submodule deinit example
+'
+
 test_done
-- 
1.8.0.1.348.gc64da69
Previous: Junio C HamanoNext: Junio C Hamano
Message 24 of 67 in “Re: [PATCH v5 0/2] submodule update: add --remote for submodule's upstream changes”
  1. W. Trevor KingNov 29, 2012
  2. Phil HordNov 30, 2012
  3. W. Trevor KingNov 30, 2012
  4. [RFC] remove/deprecate 'submodule init' and 'sync'W. Trevor King, Nov 30, 2012
  5. W. Trevor KingNov 30, 2012
  6. Phil HordNov 30, 2012
  7. W. Trevor KingDec 1, 2012
  8. Jens LehmannDec 1, 2012
  9. W. Trevor KingDec 1, 2012
  10. Jens LehmannDec 1, 2012
  11. W. Trevor KingDec 1, 2012
  12. Jens LehmannDec 1, 2012
  13. W. Trevor KingDec 1, 2012
  14. Jens LehmannDec 1, 2012
  15. W. Trevor KingDec 1, 2012
  16. submodule: add 'deinit' commandJens Lehmann, Dec 1, 2012
  17. Junio C HamanoDec 2, 2012
  18. W. Trevor KingDec 2, 2012
  19. Jens LehmannDec 2, 2012
  20. W. Trevor KingDec 2, 2012
  21. W. Trevor KingDec 3, 2012
  22. Jens LehmannDec 2, 2012
  23. Junio C HamanoDec 3, 2012
  24. submodule: add 'deinit' commandJens Lehmann, Dec 4, 2012
  25. Junio C HamanoDec 4, 2012
  26. Michael J GruberDec 12, 2012
  27. Jens LehmannDec 12, 2012
  28. Junio C HamanoDec 12, 2012
  29. Jens LehmannDec 12, 2012
  30. Junio C HamanoDec 12, 2012
  31. W. Trevor KingDec 12, 2012
  32. Junio C HamanoDec 12, 2012
  33. W. Trevor KingDec 13, 2012
  34. Marc BranchaudDec 13, 2012
  35. Jens LehmannDec 1, 2012
  36. W. Trevor KingDec 1, 2012
  37. 0/4 submodule update: add --remote for submodule's upstream changesW. Trevor King, Dec 2, 2012
  38. 1/4 submodule: add get_submodule_config helper funtionW. Trevor King, Dec 2, 2012
  39. Junio C HamanoDec 3, 2012
  40. 2/4 submodule update: add --remote for submodule's upstream changesW. Trevor King, Dec 2, 2012
  41. Junio C HamanoDec 3, 2012
  42. W. Trevor KingDec 3, 2012
  43. W. Trevor KingDec 3, 2012
  44. Junio C HamanoDec 3, 2012
  45. W. Trevor KingDec 4, 2012
  46. 0/3 submodule update: add --remote for submodule's upstream changesW. Trevor King, Dec 11, 2012
  47. 1/3 submodule: add get_submodule_config helper funtionW. Trevor King, Dec 11, 2012
  48. 2/3 submodule update: add --remote for submodule's upstream changesW. Trevor King, Dec 11, 2012
  49. Phil HordDec 12, 2012
  50. Junio C HamanoDec 12, 2012
  51. W. Trevor KingDec 12, 2012
  52. 0/3 submodule update: add --remote for submodule's upstream changeswking@tremily.us, Dec 19, 2012
  53. 1/3 submodule: add get_submodule_config helper funtionwking@tremily.us, Dec 19, 2012
  54. Heiko VoigtDec 21, 2012
  55. W. Trevor KingDec 21, 2012
  56. 2/3 submodule update: add --remote for submodule's upstream changeswking@tremily.us, Dec 19, 2012
  57. 3/3 submodule add: If --branch is given, record it in .gitmoduleswking@tremily.us, Dec 19, 2012
  58. Junio C HamanoDec 19, 2012
  59. Heiko VoigtDec 21, 2012
  60. 3/3 submodule add: If --branch is given, record it in .gitmodulesW. Trevor King, Dec 11, 2012
  61. Junio C HamanoDec 12, 2012
  62. W. Trevor KingDec 12, 2012
  63. Junio C HamanoDec 12, 2012
  64. W. Trevor KingDec 12, 2012
  65. 3/4 submodule add: If --branch is given, record it in .gitmodulesW. Trevor King, Dec 2, 2012
  66. 4/4 submodule update: add submodule.<name>.remote config optionW. Trevor King, Dec 2, 2012
  67. Jens LehmannDec 2, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.