{"thread":{"id":"31761","subject":"[PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","startedAt":"2012-10-09T00:50:10Z","lastAt":"2012-10-09T21:48:31Z","messageCount":8,"participants":["Jay Soffian","Junio C Hamano","Jens Lehmann"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"200798","messageId":"1349743810-10753-1-git-send-email-jaysoffian@gmail.com","threadId":"31761","inReplyTo":null,"subject":"[PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2012-10-09T00:50:10Z","receivedAt":"2012-10-09T00:50:10Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"Teach \"git submodule foreach\" a --revision <tree-ish> option. This\nis useful in combination with $sha1 to perform git commands that\ntake a revision argument. For example:\n\n  $ git submodule foreach --revision v1.0 'git tag v1.0 $sha1'\n\nPreviously, this would have required multiple steps:\n\n  $ git checkout v1.0\n  $ git submodule update\n  $ git submodule foreach 'git tag v1.0'\n\nSigned-off-by: Jay Soffian <jaysoffian@gmail.com>\n---\n Documentation/git-submodule.txt |  7 ++++++-\n git-submodule.sh                | 27 ++++++++++++++++++++++++---\n t/t7407-submodule-foreach.sh    | 15 +++++++++++++++\n 3 files changed, 45 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex b4683bba1b..6c889f5fd6 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -17,7 +17,8 @@ SYNOPSIS\n \t      [--reference <repository>] [--merge] [--recursive] [--] [<path>...]\n 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]\n \t      [commit] [--] [<path>...]\n-'git submodule' [--quiet] foreach [--recursive] <command>\n+'git submodule' [--quiet] foreach [--recursive] [--revision <tree-ish>]\n+\t      <command>\n 'git submodule' [--quiet] sync [--] [<path>...]\n \n \n@@ -180,6 +181,10 @@ foreach::\n \tof each submodule before evaluating the command.\n \tIf `--recursive` is given, submodules are traversed recursively (i.e.\n \tthe given shell command is evaluated in nested submodules as well).\n+\tIf `--revision <tree-ish>` is given, submodules are traversed starting\n+\tat the given <tree-ish>. Though this does not alter the submodule check\n+\touts, it may be combined with $sha1 to perform git commands that can\n+\toperate\ton a particular commit, such as linkgit:git-tag[1].\n \tA non-zero return from the command in any submodule causes\n \tthe processing to terminate. This can be overridden by adding '|| :'\n \tto the end of the command.\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex ab6b1107b6..5e7458e155 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -10,7 +10,7 @@ USAGE=\"[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <r\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n-   or: $dashless [--quiet] foreach [--recursive] <command>\n+   or: $dashless [--quiet] foreach [--recursive] [--revision <tree-ish>] <command>\n    or: $dashless [--quiet] sync [--] [<path>...]\"\n OPTIONS_SPEC=\n . git-sh-setup\n@@ -379,6 +379,7 @@ Use -f if you really want to add it.\" >&2\n cmd_foreach()\n {\n \t# parse $args after \"submodule ... foreach\".\n+\trevision=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -388,6 +389,11 @@ cmd_foreach()\n \t\t--recursive)\n \t\t\trecursive=1\n \t\t\t;;\n+\t\t--revision)\n+\t\t\tgit rev-parse --quiet --verify \"$2\" >/dev/null || usage\n+\t\t\trevision=$2\n+\t\t\tshift\n+\t\t\t;;\n \t\t-*)\n \t\t\tusage\n \t\t\t;;\n@@ -404,7 +410,17 @@ cmd_foreach()\n \t# command in the subshell (and a recursive call to this function)\n \texec 3<&0\n \n-\tmodule_list |\n+\tif test -n \"$revision\"\n+\tthen\n+\t\t# make ls-tree output look like ls-files output\n+\t\tgit ls-tree -r $revision | grep '^160000 ' |\n+\t\twhile read mode unused sha1 sm_path\n+\t\tdo\n+\t\t\techo \"$mode $sha1 0 $sm_path\"\n+\t\tdone\n+\telse\n+\t\tmodule_list\n+\tfi |\n \twhile read mode sha1 stage sm_path\n \tdo\n \t\tdie_if_unmatched \"$mode\"\n@@ -421,7 +437,12 @@ cmd_foreach()\n \t\t\t\teval \"$@\" &&\n \t\t\t\tif test -n \"$recursive\"\n \t\t\t\tthen\n-\t\t\t\t\tcmd_foreach \"--recursive\" \"$@\"\n+\t\t\t\t\tif test -n \"$revision\"\n+\t\t\t\t\tthen\n+\t\t\t\t\t\tcmd_foreach \"--recursive\" \"--revision\" \"$sha1\" \"$@\"\n+\t\t\t\t\telse\n+\t\t\t\t\t\tcmd_foreach \"--recursive\" \"$@\"\n+\t\t\t\t\tfi\n \t\t\t\tfi\n \t\t\t) <&3 3<&- ||\n \t\t\tdie \"$(eval_gettext \"Stopping at '\\$sm_path'; script returned non-zero status.\")\"\ndiff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh\nindex 9b69fe2e14..5c798b901b 100755\n--- a/t/t7407-submodule-foreach.sh\n+++ b/t/t7407-submodule-foreach.sh\n@@ -179,6 +179,21 @@ test_expect_success 'test \"foreach --quiet --recursive\"' '\n \ttest_cmp expect actual\n '\n \n+sha1=$(cd submodule && git rev-parse HEAD~1)\n+cat > expect <<EOF\n+sub1 $sha1\n+sub2 $sha1\n+sub3 $sha1\n+EOF\n+\n+test_expect_success 'test \"foreach --quiet --revision\"' '\n+\t(\n+\t\tcd clone2 &&\n+\t\tgit submodule foreach -q --revision HEAD~2 \"echo \\$path \\$sha1\" > ../actual\n+\t) &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'use \"update --recursive\" to checkout all submodules' '\n \tgit clone super clone3 &&\n \t(\n-- \n1.7.12.2\n"},{"id":"200814","messageId":"7v8vbgi3yz.fsf@alter.siamese.dyndns.org","threadId":"31761","inReplyTo":"1349743810-10753-1-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-10-09T05:55:48Z","receivedAt":"2012-10-09T05:55:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> Teach \"git submodule foreach\" a --revision <tree-ish> option. This\n> is useful in combination with $sha1 to perform git commands that\n> take a revision argument.\n\nThe above says:\n\n - \"--revision T\" is added.\n\n   OK.  There is no information whatsoever what it does to convince\n   us why it is useful.\n\n - This is useful.\n\n   Huh?  How can anybody supposed to agree or disagree with that\n   claim, when nothing is said about what it does in the first\n   place?\n\n> For example:\n>\n>   $ git submodule foreach --revision v1.0 'git tag v1.0 $sha1'\n\nWhose \"v1.0\" does this example refer to?\n\nThe first line of the proposed log message says it is <tree-ish>,\nwhich means that you can safely substitute \"--revision T\" with\n\"--revision $(git rev-parse T^{tree}), so it must name a concrete\nsingle object that is a tree (not a tree-ish).  In which repository\nis that object found?  The top-level superproject?  All submodule\nrepositories share the same object store with the superproject?\n\nThe description doesn't make _any_ sense to me. The feature might be\nsomething worth considering about with a better description, but\nwith the above, I can't tell if it is.\n\n> +\tIf `--revision <tree-ish>` is given, submodules are traversed starting\n> +\tat the given <tree-ish>.\n\nWhat does \"are traversed starting at the given <tree-ish>\"?  The\ndesired or expected state of each submodule is recorded as a commit\nobject name (not even commit-ish) in its superproject.  Did you mean\n\"commit-ish\"?\n\n> + Though this does not alter the submodule check\n> +\touts, it may be combined with $sha1 to perform git commands that can\n> +\toperate\ton a particular commit, such as linkgit:git-tag[1].\n\nHere is what I am guessing, partially with help from the horrible example:\n\n>   $ git submodule foreach --revision v1.0 'git tag v1.0 $sha1'\n>\n> Previously, this would have required multiple steps:\n>\n>   $ git checkout v1.0\n>   $ git submodule update\n>   $ git submodule foreach 'git tag v1.0'\n\nwhere there appears two v1.0 that are used for totally different\npurposes which does not help guessing.  Perhaps \"--revision\" names a\ntree-ish taken from the top-level superproject, and for each\nsubmodule that appear in the tree in the superproject, the command\nspecified by foreach is run with the usual $sha1, $name, $path set\nto the state in the submodules that top-level tree wants to have,\nand this is done without actually checking anything out.  So the\nfirst v1.0 in that confusing example is about specifying a tree in\nthe superproject repository, and the second v1.0 does not have any\nrelationship with that first v1.0 (the first one could have been HEAD~2\nwhen you have committed twice in the superproject since you tagged v1.0\nand remembered that you forgot to tag its submodules).\n\nAssuming that the above guess is correct (which is a huge\nassumption, given the lack of clarity in the description), I think\nthe feature might make sense.  The example would have been a lot\neasier to follow if it were something like this:\n\n    $ git submodule foreach --revision v1.0 'git grep -e frotz $sha1'\n\n> @@ -379,6 +379,7 @@ Use -f if you really want to add it.\" >&2\n>  cmd_foreach()\n>  {\n>  \t# parse $args after \"submodule ... foreach\".\n> +\trevision=\n>  \twhile test $# -ne 0\n>  \tdo\n>  \t\tcase \"$1\" in\n> @@ -388,6 +389,11 @@ cmd_foreach()\n>  \t\t--recursive)\n>  \t\t\trecursive=1\n>  \t\t\t;;\n> +\t\t--revision)\n> +\t\t\tgit rev-parse --quiet --verify \"$2\" >/dev/null || usage\n> +\t\t\trevision=$2\n\nShouldn't this part of the code verify $2^{tree} instead to ensure\nthat \"$2\" is a tree-ish?\n\n> +\t\t\tshift\n> +\t\t\t;;\n>  \t\t-*)\n>  \t\t\tusage\n>  \t\t\t;;\n> @@ -404,7 +410,17 @@ cmd_foreach()\n>  \t# command in the subshell (and a recursive call to this function)\n>  \texec 3<&0\n>  \n> -\tmodule_list |\n> +\tif test -n \"$revision\"\n> +\tthen\n> +\t\t# make ls-tree output look like ls-files output\n> +\t\tgit ls-tree -r $revision | grep '^160000 ' |\n> +\t\twhile read mode unused sha1 sm_path\n> +\t\tdo\n> +\t\t\techo \"$mode $sha1 0 $sm_path\"\n> +\t\tdone\n> +\telse\n> +\t\tmodule_list\n> +\tfi |\n\nHrm, it is somewhat unfortunate that you cannot limit the set of\nsubmodules to apply foreach to, like other commands like init,\nupdate, status, etc.  (not a new problem).\n"},{"id":"200817","messageId":"7v4nm4i37u.fsf@alter.siamese.dyndns.org","threadId":"31761","inReplyTo":"7v8vbgi3yz.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-10-09T06:12:05Z","receivedAt":"2012-10-09T06:12:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Assuming that the above guess is correct (which is a huge\n> assumption, given the lack of clarity in the description), I think\n> the feature might make sense.  The example would have been a lot\n> easier to follow if it were something like this:\n>\n>     $ git submodule foreach --revision v1.0 'git grep -e frotz $sha1'\n\nImagine you have a checkout of v2.0 of the superproject in your\nworking tree, and you run \"git submodule foreach --revision v1.0\".\nFurther imagine a submodule S that used to exist back when the\nsuperproject was at v1.0 no longer exists in the current codebase\n(hence there is no such submodule in the working tree).\n\nShouldn't the above \"foreach ... grep\" still try to find 'frotz' in\nthe submodule S that was bound to v1.0 of the superproject?\n\nGiven that your patch does not touch the part of cmd_foreach where\nit decides which submodule to descend into, it still will base its\ndecision solely on the set of submodules that are bound to and have\nbeen \"git submodule init\"ed in the version of the superproject that\nis _currently_ checked out, no?\n"},{"id":"200820","messageId":"CAG+J_Dw1iXJfgkmA2V-L11xCOOxO57U4Dh7=h7AzkFUqLc55=w@mail.gmail.com","threadId":"31761","inReplyTo":"7v4nm4i37u.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2012-10-09T06:50:10Z","receivedAt":"2012-10-09T06:50:10Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Oct 9, 2012 at 2:12 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> Assuming that the above guess is correct (which is a huge\n>> assumption, given the lack of clarity in the description), I think\n>> the feature might make sense.  The example would have been a lot\n>> easier to follow if it were something like this:\n>>\n>>     $ git submodule foreach --revision v1.0 'git grep -e frotz $sha1'\n>\n> Imagine you have a checkout of v2.0 of the superproject in your\n> working tree, and you run \"git submodule foreach --revision v1.0\".\n> Further imagine a submodule S that used to exist back when the\n> superproject was at v1.0 no longer exists in the current codebase\n> (hence there is no such submodule in the working tree).\n>\n> Shouldn't the above \"foreach ... grep\" still try to find 'frotz' in\n> the submodule S that was bound to v1.0 of the superproject?\n>\n> Given that your patch does not touch the part of cmd_foreach where\n> it decides which submodule to descend into, it still will base its\n> decision solely on the set of submodules that are bound to and have\n> been \"git submodule init\"ed in the version of the superproject that\n> is _currently_ checked out, no?\n\nThat's a good observation. My use-case for this (poorly explained in\nthe commit message) is as part of a release process, where I wish to\napply corresponding tags to the superproject and its submodules like\nso:\n\n$ cd /path/to/superproject\n$ git tag -m \"1.0\" v1.0 deadbeef\n$ git submodule foreach --revision deadbeef \\\n  'git tag -m \"superproject 1.0\" superproject-1.0 $sha1'\n\nTypically deadbeef may be a day or two behind HEAD and it's nice to be\nable to tag it and the submodules w/o having to switch everything to a\ndetached HEAD. In my case, tagging and updating submodule revisions\nare somewhat common, while adding/removing submodules is a rare event.\n\nI didn't mention this issue explicitly because I thought it was\ncovered by the existing documentation: \"Any submodules defined in the\nsuperproject but not checked out are ignored by this command.\"\n\nAs you previously stated, I need to improve the documentation that\ngoes along with this patch, so I'll call-out this limitation. I'm not\nsure what else can be done. You can't descend into a submodule that\nisn't there.\n\nj.\n"},{"id":"200851","messageId":"7vr4p7fqr2.fsf@alter.siamese.dyndns.org","threadId":"31761","inReplyTo":"CAG+J_Dw1iXJfgkmA2V-L11xCOOxO57U4Dh7=h7AzkFUqLc55=w@mail.gmail.com","subject":"Re: [PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-10-09T18:24:17Z","receivedAt":"2012-10-09T18:24:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> On Tue, Oct 9, 2012 at 2:12 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Junio C Hamano <gitster@pobox.com> writes:\n>>\n>>> Assuming that the above guess is correct (which is a huge\n>>> assumption, given the lack of clarity in the description), I think\n>>> the feature might make sense.  The example would have been a lot\n>>> easier to follow if it were something like this:\n>>>\n>>>     $ git submodule foreach --revision v1.0 'git grep -e frotz $sha1'\n>>\n>> Imagine you have a checkout of v2.0 of the superproject in your\n>> working tree, and you run \"git submodule foreach --revision v1.0\".\n>> Further imagine a submodule S that used to exist back when the\n>> superproject was at v1.0 no longer exists in the current codebase\n>> (hence there is no such submodule in the working tree).\n>>\n>> Shouldn't the above \"foreach ... grep\" still try to find 'frotz' in\n>> the submodule S that was bound to v1.0 of the superproject?\n>>\n>> Given that your patch does not touch the part of cmd_foreach where\n>> it decides which submodule to descend into, it still will base its\n>> decision solely on the set of submodules that are bound to and have\n>> been \"git submodule init\"ed in the version of the superproject that\n>> is _currently_ checked out, no?\n>\n> That's a good observation. My use-case for this (poorly explained in\n> ...\n> As you previously stated, I need to improve the documentation that\n> goes along with this patch, so I'll call-out this limitation. I'm not\n> sure what else can be done. You can't descend into a submodule that\n> isn't there.\n\nAs recent \"submodule rm\" work by Jens indicates, since 501770e (Move\ngit-dir for submodules, 2011-08-15), you should be able to peek into\nsubmodules that have been \"git submodule init\"ed but do not exist in\nthe current checkout of the superproject.\n\nI think the right approach to implement this \"recurse foreach in the\nsuperproject tree that is not checkout out to the working tree\"\nfeature should be:\n\n - Advertise it so that it is crystal clear that the command run by\n   \"foreach\" may have to run in a bare repository of submodule to\n   look at submodule's commit bound to the historical tree of the\n   superproject;\n\n - Anytime you look at .gitmodules in the superproject, read from\n   the historical tree's .gitmodules instead of from the working\n   tree (I think this is necessary in order to get the $sm_name vs\n   $sm_path mapping right); and\n\n - Locate submodule's $GIT_DIR in $GIT_DIR/modules/$sm_name of the\n   superproject that corresponds to the submodule found in the\n   historical tree in the superproject (or if it is the same\n   repository as that is currently checked out, use $sm_path/.git),\n   and error out when it is not available.\n\nAn implementation that works only when all the submodules necessary\nin the historical tree in the superproject are still in the current\ncheckout of the superproject may be fine as a quick throw-away hack,\nand it may even be acceptable as a good first step towards the real\nfeature, but at least it needs to be protected by an error checking\nupfront (perhaps running \"diff-tree -r\" between the index and the\nhistorical tree to make sure there are no removed submodules that\nexisted in the historical tree), if it does not bother to check with\n$GIT_DIR/modules/$sm_name in the superproject.\n\nJens, anything I missed?\n"},{"id":"200862","messageId":"5074956E.3060909@web.de","threadId":"31761","inReplyTo":"7vr4p7fqr2.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2012-10-09T21:21:50Z","receivedAt":"2012-10-09T21:21:50Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 09.10.2012 20:24, schrieb Junio C Hamano:\n> Jay Soffian <jaysoffian@gmail.com> writes:\n> \n>> On Tue, Oct 9, 2012 at 2:12 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Junio C Hamano <gitster@pobox.com> writes:\n>>>\n>>>> Assuming that the above guess is correct (which is a huge\n>>>> assumption, given the lack of clarity in the description), I think\n>>>> the feature might make sense.  The example would have been a lot\n>>>> easier to follow if it were something like this:\n>>>>\n>>>>     $ git submodule foreach --revision v1.0 'git grep -e frotz $sha1'\n>>>\n>>> Imagine you have a checkout of v2.0 of the superproject in your\n>>> working tree, and you run \"git submodule foreach --revision v1.0\".\n>>> Further imagine a submodule S that used to exist back when the\n>>> superproject was at v1.0 no longer exists in the current codebase\n>>> (hence there is no such submodule in the working tree).\n>>>\n>>> Shouldn't the above \"foreach ... grep\" still try to find 'frotz' in\n>>> the submodule S that was bound to v1.0 of the superproject?\n>>>\n>>> Given that your patch does not touch the part of cmd_foreach where\n>>> it decides which submodule to descend into, it still will base its\n>>> decision solely on the set of submodules that are bound to and have\n>>> been \"git submodule init\"ed in the version of the superproject that\n>>> is _currently_ checked out, no?\n>>\n>> That's a good observation. My use-case for this (poorly explained in\n>> ...\n>> As you previously stated, I need to improve the documentation that\n>> goes along with this patch, so I'll call-out this limitation. I'm not\n>> sure what else can be done. You can't descend into a submodule that\n>> isn't there.\n> \n> As recent \"submodule rm\" work by Jens indicates, since 501770e (Move\n> git-dir for submodules, 2011-08-15), you should be able to peek into\n> submodules that have been \"git submodule init\"ed but do not exist in\n> the current checkout of the superproject.\n> \n> I think the right approach to implement this \"recurse foreach in the\n> superproject tree that is not checkout out to the working tree\"\n> feature should be:\n> \n>  - Advertise it so that it is crystal clear that the command run by\n>    \"foreach\" may have to run in a bare repository of submodule to\n>    look at submodule's commit bound to the historical tree of the\n>    superproject;\n\nI think we should even try to enforce that the user shouldn't use\nthe work tree at all (although at the moment I can't come up with\nan idea how we could do that), as the work tree *will* be out of\nsync almost always when you need this option. Otherwise strange\nthings would happen when using \"git submodule foreach --revision\n...\" with a command which examines the work tree, as that won't be\nupdated to the given revision.\n\n>  - Anytime you look at .gitmodules in the superproject, read from\n>    the historical tree's .gitmodules instead of from the working\n>    tree (I think this is necessary in order to get the $sm_name vs\n>    $sm_path mapping right); and\n\nYes, that is definitely necessary in case submodules are added,\nremoved or moved.\n\n>  - Locate submodule's $GIT_DIR in $GIT_DIR/modules/$sm_name of the\n>    superproject that corresponds to the submodule found in the\n>    historical tree in the superproject (or if it is the same\n>    repository as that is currently checked out, use $sm_path/.git),\n>    and error out when it is not available.\n\nLooking in $GIT_DIR/modules/$sm_name could make sense to tag even\nthose submodules which aren't currently populated. But IIRC the\ntags in such repositories could not be pushed using current git\neven when you use the \"--recurse-submodules\" option because that\nonly honors populated submodules. So for now it would suffice to\nonly recurse into populated submodules.\n\n> An implementation that works only when all the submodules necessary\n> in the historical tree in the superproject are still in the current\n> checkout of the superproject may be fine as a quick throw-away hack,\n> and it may even be acceptable as a good first step towards the real\n> feature, but at least it needs to be protected by an error checking\n> upfront (perhaps running \"diff-tree -r\" between the index and the\n> historical tree to make sure there are no removed submodules that\n> existed in the historical tree), if it does not bother to check with\n> $GIT_DIR/modules/$sm_name in the superproject.\n> \n> Jens, anything I missed?\n\nNothing I can think of right now, the above is a pretty good summary.\nMy gut feeling is that having \"git submodule foreach --revision ...\"\nrecurse through submodules whose work trees are out of sync is pretty\nfragile and could easily lead to inconsistencies. So I tend to think\nadding a custom script to the release process Jay uses which does the\ntagging itself might be a better solution here. Opinions?\n"},{"id":"200864","messageId":"CAG+J_DxeqPU=rLeJj0fR6Ojo7S=3fhStCo=xMXoO3CFYGMYZ3Q@mail.gmail.com","threadId":"31761","inReplyTo":"5074956E.3060909@web.de","subject":"Re: [PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2012-10-09T21:38:07Z","receivedAt":"2012-10-09T21:38:07Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Oct 9, 2012 at 5:21 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:\n> Nothing I can think of right now, the above is a pretty good summary.\n> My gut feeling is that having \"git submodule foreach --revision ...\"\n> recurse through submodules whose work trees are out of sync is pretty\n> fragile and could easily lead to inconsistencies. So I tend to think\n> adding a custom script to the release process Jay uses which does the\n> tagging itself might be a better solution here. Opinions?\n\nI agree now that this is a perilous option, and that its use case may\nbe so narrow that it may not worth adding. I am indeed already using a\ncustom script, and maybe I should leave it at that.\n\nj.\n"},{"id":"200865","messageId":"7va9vve2q8.fsf@alter.siamese.dyndns.org","threadId":"31761","inReplyTo":"5074956E.3060909@web.de","subject":"Re: [PATCH] submodule: teach \"foreach\" command a --revision <tree-ish> option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-10-09T21:48:31Z","receivedAt":"2012-10-09T21:48:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jens Lehmann <Jens.Lehmann@web.de> writes:\n\n> Am 09.10.2012 20:24, schrieb Junio C Hamano:\n> ...\n>> I think the right approach to implement this \"recurse foreach in the\n>> superproject tree that is not checkout out to the working tree\"\n>> feature should be:\n>> \n>>  - Advertise it so that it is crystal clear that the command run by\n>>    \"foreach\" may have to run in a bare repository of submodule to\n>>    look at submodule's commit bound to the historical tree of the\n>>    superproject;\n>\n> I think we should even try to enforce that the user shouldn't use\n> the work tree at all (although at the moment I can't come up with\n> an idea how we could do that), as the work tree *will* be out of\n> sync almost always when you need this option.\n\nVery good point.\n\n>>  - Locate submodule's $GIT_DIR in $GIT_DIR/modules/$sm_name of the\n>>    superproject that corresponds to the submodule found in the\n>>    historical tree in the superproject (or if it is the same\n>>    repository as that is currently checked out, use $sm_path/.git),\n>>    and error out when it is not available.\n>\n> Looking in $GIT_DIR/modules/$sm_name could make sense to tag even\n> those submodules which aren't currently populated. But IIRC the\n> tags in such repositories could not be pushed using current git\n> even when you use the \"--recurse-submodules\" option because that\n> only honors populated submodules. So for now it would suffice to\n> only recurse into populated submodules.\n\nThere are million reasons why we shouldn't lightly think \"recurse\nsubmodules is a good idea\", and I think this may be one of them.\n\nBut you can always go to $GIT_DIR/modules/$sm_name and push from\nthere, so I do not see it as a huge problem.\n\n>> Jens, anything I missed?\n>\n> Nothing I can think of right now, the above is a pretty good summary.\n> My gut feeling is that having \"git submodule foreach --revision ...\"\n> recurse through submodules whose work trees are out of sync is pretty\n> fragile and could easily lead to inconsistencies. So I tend to think\n> adding a custom script to the release process Jay uses which does the\n> tagging itself might be a better solution here. Opinions?\n\nWell, I am not a good judge for that, as I've never been a big fan\nof \"submodule recurse\" myself anyway.  But I think an addition that\nworks only when the user never uses commands that use the working\ntree or the index is still a good thing to have.\n\nWe could export a magic environment while running foreach script and\nmake NEED_WORK_TREE check fail when it is set, or something, but we\nneed to be careful about performance implications.  \"foreach\" is not\nsomething that is worth sacrificing the general performance over.\n"}]}