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

[PATCH 2/2] git-submodule: support 'rm' command.

From
Michał Górny <mgorny@gentoo.org>
Date
Jun 25, 2012, 10:57 UTC
Message-ID
<1340621820-19448-2-git-send-email-mgorny@gentoo.org>
In-Reply-To
<1340621820-19448-1-git-send-email-mgorny@gentoo.org>

Add an 'rm' command to git-submodule which provides means to (semi-)easily remove git submodules.

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
Right now, it requires the submodule checkout to be removed manually
first (so it does not remove unstaged commits), and just removes
the index entry and module information from config.

I based it on 'cmd_add' code trying to preserve the original coding standards.

 Documentation/git-submodule.txt |   12 +++++++
 git-submodule.sh                |   68 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index fbbbcb2..293c1bf 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git submodule' [--quiet] add [-b branch] [-f|--force]
 	      [--reference <repository>] [--] <repository> [<path>]
+'git submodule' [--quiet] rm <path>...
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
@@ -104,6 +105,17 @@ together in the same relative location, and only the
 superproject's URL needs to be provided: git-submodule will correctly
 locate the submodule using the relative URL in .gitmodules.
 
+rm::
+	Remove and unregister the submodules at given paths.
++
+This requires at least one <path> argument. The repository checkout
+existing at that directory needs to be removed manually from
+the filesystem prior to calling this command. Note that all local
+changes will be lost.
++
+This command removes the submodule from the current git index,
+the .gitmodules file and the local repository config.
+
 status::
 	Show the status of the submodules. This will print the SHA-1 of the
 	currently checked out commit for each submodule, along with the
diff --git a/git-submodule.sh b/git-submodule.sh
index fbf2faf..88fd414 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -6,6 +6,7 @@
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
+   or: $dashless [--quiet] rm [--] <path>...
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
@@ -308,6 +309,71 @@ Use -f if you really want to add it." >&2
 }
 
 #
+# Remove submodules from the working tree, .gitmodules and the index
+#
+# $@ = submodule paths
+#
+cmd_rm()
+{
+	# parse $args after "submodule ... rm".
+	while test $# -ne 0
+	do
+		case "$1" in
+		--)
+			shift
+			break
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
+	if test -z "$1"; then
+		usage
+	fi
+
+	while test $# -ne 0
+	do
+		sm_path=$1
+		shift
+
+		# normalize path:
+		# multiple //; leading ./; /./; /../; trailing /
+		sm_path=$(printf '%s/\n' "$sm_path" |
+			sed -e '
+				s|//*|/|g
+				s|^\(\./\)*||
+				s|/\./|/|g
+				:start
+				s|\([^/]*\)/\.\./||
+				tstart
+				s|/*$||
+			')
+		git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 ||
+		die "$(eval_gettext "'\$sm_path' does not exist in the index")"
+
+		if test -e "$sm_path"
+		then
+			die "$(eval_gettext "'\$sm_path' needs to be removed manually first")"
+		fi
+
+		git rm --cached "$sm_path" ||
+		die "$(eval_gettext "Failed to remove submodule '\$sm_path'")"
+
+		git config -f .gitmodules --remove-section submodule."$sm_path" &&
+		git add --force .gitmodules ||
+		die "$(eval_gettext "Failed to unregister submodule '\$sm_path'")"
+
+		git config --remove-section submodule."$sm_path"
+	done
+}
+
+#
 # Execute an arbitrary command sequence in each checked out
 # submodule
 #
@@ -996,7 +1062,7 @@ cmd_sync()
 while test $# != 0 && test -z "$command"
 do
 	case "$1" in
-	add | foreach | init | update | status | summary | sync)
+	add | rm | foreach | init | update | status | summary | sync)
 		command=$1
 		;;
 	-q|--quiet)
-- 
1.7.10.2
Previous: Michał GórnyNext: Jens Lehmann
Message 2 of 9 in “git-submodule.sh: fix filename in comment.”
  1. 1/2 git-submodule.sh: fix filename in comment.Michał Górny, Jun 25, 2012
  2. 2/2 git-submodule: support 'rm' command.Michał Górny, Jun 25, 2012
  3. Jens LehmannJun 25, 2012
  4. Phil HordJun 25, 2012
  5. Jens LehmannJun 25, 2012
  6. Phil HordJun 26, 2012
  7. Jens LehmannJun 26, 2012
  8. Phil HordJun 27, 2012
  9. Michał GórnyJun 28, 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.