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

[PATCH] git-submodule - Add 'foreach' subcommand

From
Mark Levedahl <mlevedahl@gmail.com>
Date
Aug 10, 2008, 23:10 UTC
Message-ID
<1218409804-1556-1-git-send-email-mlevedahl@gmail.com>
In-Reply-To
<7vsktczebg.fsf@gitster.siamese.dyndns.org>

submodule foreach <command-list> will execute the list of commands in each currently checked out submodule directory. The list of commands is arbitrary as long as it is acceptable to sh. The variables '$path' and '$sha1' are availble to the command-list, defining the submodule path relative to the superproject and the submodules's commitID as recorded in the superproject (this may be different than HEAD in the submodule).

This utility is inspired by a number of threads on the mailing list looking for ways to better integrate submodules in a tree and work with them as a unit. This could include fetching a new branch in each from a given source, or possibly checking out a given named branch in each. Currently, there is no consensus as to what additional commands should be implemented in the porcelain, requiring all users whose needs exceed that of git-submodule to do their own scripting. The foreach command is intended to support such scripting, and in particular does no error checking and produces no output, thus allowing end users complete control over any information printed out and over what constitutes an error. The processing does terminate if the command-list returns an error, but processing can easily be forced for all submodules be terminating the list with ';true'.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
 Documentation/git-submodule.txt |   15 +++++++++++++++
 git-submodule.sh                |   23 +++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index bf33b0c..1e7d352 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -14,6 +14,7 @@ SYNOPSIS
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [--] [<path>...]
 'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
+'git submodule' foreach <command-list>
 
 
 DESCRIPTION
@@ -123,6 +124,20 @@ summary::
 	in the submodule between the given super project commit and the
 	index or working tree (switched by --cached) are shown.
 
+foreach::
+	Executes an arbitrary list of commands in each checked out submodule.
+	$path is the name of the submodule directory relative to the
+	superproject, and $sha1 is the commit as recorded in the superproject.
+	Any submodules defined in the superproject but not checked out are
+	ignored by this command, and an empty command-list provides no output.
+	A non-zero return from the command-list in any submodule causes
+	the processing to terminate. This can be overridden by adding '; true'
+	to the end of the command list.
++
+As an example, "git submodule foreach 'echo $path `git rev-parse HEAD`' will
+show the path and currently checked out commit for each submodule.
+
+
 OPTIONS
 -------
 -q::
diff --git a/git-submodule.sh b/git-submodule.sh
index b40f876..39a19f0 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -6,7 +6,7 @@
 
 USAGE="[--quiet] [--cached] \
 [add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
-[--] [<path>...]"
+[--] [<path>...]|[foreach <command-list>]"
 OPTIONS_SPEC=
 . git-sh-setup
 require_work_tree
@@ -199,6 +199,25 @@ cmd_add()
 }
 
 #
+# Execute an arbitrary command sequence in each checked out
+# submodule
+#
+# $@ = command to execute
+#
+cmd_foreach()
+{
+	git ls-files --stage | grep '^160000 ' |
+	while read mode sha1 stage path
+	do
+		if test -e "$path"/.git
+		then
+			(cd "$path" && eval "$@") ||
+			die "Error detected evaluating commands in '$path'"
+		fi
+	done
+}
+
+#
 # Register submodules in .git/config
 #
 # $@ = requested paths (default to all)
@@ -583,7 +602,7 @@ cmd_status()
 while test $# != 0 && test -z "$command"
 do
 	case "$1" in
-	add | init | update | status | summary)
+	add | foreach | init | update | status | summary)
 		command=$1
 		;;
 	-q|--quiet)
-- 
1.6.0.rc2.44.g974eb
Previous: Junio C HamanoNext: Balazs Nagy
Message 4 of 10 in “git-submodule - Add 'foreach' subcommand”
  1. git-submodule - Add 'foreach' subcommandMark Levedahl, Aug 10, 2008
  2. Johan HerlandAug 10, 2008
  3. Junio C HamanoAug 10, 2008
  4. git-submodule - Add 'foreach' subcommandMark Levedahl, Aug 10, 2008
  5. Balazs NagyAug 11, 2008
  6. Johannes SchindelinAug 11, 2008
  7. Matthias KestenholzAug 11, 2008
  8. Petr BaudisAug 11, 2008
  9. Junio C HamanoAug 11, 2008
  10. git-submodule foreach - Include output and clarify usage.Mark Levedahl, Aug 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.