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

[PATCH 2/3] git-submodule - Allow adding a submodule in-place

From
Mark Levedahl <mlevedahl@gmail.com>
Date
Feb 9, 2008, 16:57 UTC
Message-ID
<1202576245-284-2-git-send-email-mlevedahl@gmail.com>
In-Reply-To
<1202576245-284-1-git-send-email-mlevedahl@gmail.com>

When working in top-level project, it is useful to create a new submodule as a git repo in a subdirectory, then add that submodule to top-level in place. This allows "git submodule add <intended url> subdir" to add the existing subdir to the current project. The presumption is the user will later push / clone the subdir to the <intended url> so that future submodule init / updates will work.

Absent this patch, "git submodule add" insists upon cloning the subdir from a repository at the given url, which is fine for adding an existing project in but less useful when adding a new submodule from scratch to an existing project. The former functionality remains, and the clone is attempted if the subdir does not already exist as a valid git repo.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
 Documentation/git-submodule.txt |    5 ++-
 git-submodule.sh                |   57 +++++++++++++++++++++++---------------
 2 files changed, 37 insertions(+), 25 deletions(-)
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 4fc17f6..85d7dd3 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -18,8 +18,9 @@ COMMANDS
 --------
 add::
 	Add the given repository as a submodule at the given path
-	to the changeset to be committed next.  In particular, the
-	repository is cloned at the specified path, added to the
+	to the changeset to be committed next.  If path is a valid
+	repository within the project, it is added as is. Otherwise,
+	repository is cloned at the specified path. path is added to the
 	changeset and registered in .gitmodules.   If no path is
 	specified, the path is deduced from the repository specification.
 	If the repository url begins with ./ or ../, it is stored as
diff --git a/git-submodule.sh b/git-submodule.sh
index b97bf18..4c86a3c 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -166,23 +166,6 @@ cmd_add()
 		usage
 	fi
 
-	case "$repo" in
-	./*|../*)
-		# dereference source url relative to parent's url
-		realremote=${remote:-$(get_default_remote)}
-		realrepo=$(resolve_relative_url $repo) || exit 1
-		;;
-	*)
-		# Turn the source into an absolute path if
-		# it is local
-		if base=$(get_repo_base "$repo"); then
-			repo="$base"
-		fi
-		realremote=origin
-		realrepo=$repo
-		;;
-	esac
-
 	# Guess path from repo if not specified or strip trailing slashes
 	if test -z "$path"; then
 		path=$(echo "$repo" | sed -e 's|/*$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
@@ -190,15 +173,43 @@ cmd_add()
 		path=$(echo "$path" | sed -e 's|/*$||')
 	fi
 
-	test -e "$path" &&
-	die "'$path' already exists"
-
 	git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
 	die "'$path' already exists in the index"
 
-	module_clone "$path" "$realrepo" "$realremote" || exit
-	(unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "$realremote/$branch"}) ||
-	die "Unable to checkout submodule '$path'"
+	# perhaps the path exists and is already a git repo, else clone it
+	if test -e "$path"
+	then
+		if test -d "$path/.git" &&
+		test "$(unset GIT_DIR; cd $path; git rev-parse --git-dir)" = ".git"
+		then
+			echo "Adding existing repo at '$path' to the index"
+		else
+			die "'$path' already exists and is not a valid git repo"
+		fi
+	else
+		case "$repo" in
+		./*|../*)
+			# dereference source url relative to parent's url
+			realremote=${remote:-$(get_default_remote)}
+			realrepo=$(resolve_relative_url $repo) || exit 1
+			;;
+		*)
+			# Turn the source into an absolute path if
+			# it is local
+			if base=$(get_repo_base "$repo")
+			then
+				repo="$base"
+			fi
+			realremote=origin
+			realrepo=$repo
+			;;
+		esac
+
+		module_clone "$path" "$realrepo" "$realremote" || exit
+		(unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "$realremote/$branch"}) ||
+		die "Unable to checkout submodule '$path'"
+	fi
+
 	git add "$path" ||
 	die "Failed to add submodule '$path'"
 
-- 
1.5.4.47.gcca7b3
Previous: Mark LevedahlNext: Mark Levedahl
Message 2 of 8 in “git-submodule - Follow top-level remote on init/update/clone”
  1. 1/3 git-submodule - Follow top-level remote on init/update/cloneMark Levedahl, Feb 9, 2008
  2. 2/3 git-submodule - Allow adding a submodule in-placeMark Levedahl, Feb 9, 2008
  3. 3/3 Add t/t7401 - test submodule interaction with remotes machineryMark Levedahl, Feb 9, 2008
  4. Ping YinMar 3, 2008
  5. Johannes SchindelinFeb 11, 2008
  6. Mark LevedahlFeb 12, 2008
  7. Johannes SchindelinFeb 12, 2008
  8. Mark LevedahlFeb 12, 2008

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.