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

Re: [PATCH/RFC] Changing submodule foreach --recursive to be depth-first, --parent option to execute command in supermodule as well

From
ECEric Cousineau <eacousineau@gmail.com>
Date
Mar 26, 2013, 04:36 UTC
Message-ID
<515125CE.3020101@gmail.com>
In-Reply-To
<51511C62.3080704@gmail.com>
On 03/25/2013 10:56 PM, Eric Cousineau wrote:
> On 03/18/2013 04:10 PM, Jens Lehmann wrote:
>> Am 12.03.2013 17:01, schrieb Phil Hord:
>>> On Sat, Mar 9, 2013 at 1:18 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
>>>> Am 05.03.2013 22:17, schrieb Phil Hord:
...
Show 114 quoted lines
>>
>> I agree on the possible problems a configuration option introduces.
>>
>>>> I'm still not convinced we should add a new switch, as it can easily
>>>> be achieved by adding "${cmd} &&" to your scripts. And on the command
>>>> line you could use an alias like this one to achieve that:
>>>>
>>>> [alias]
>>>>           recurse = !sh -c \"$@ && git submodule foreach --recursive $@\"
>>>
>
> I tried this and the 'recurse-post' alias, but could not get it to function as
> it does inside of 'git submodule foreach'. I also tried out some different escaping
> methods, but nothing seemed to work. I've added the examples below.
>
>>> Yes, making the feature itself a 2nd-class citizen.  :-)
>>>
>>> But this alias also denies me the benefit of the --post-order option.
>>> For 'git recurse git push', for example, I wouldn't want the
>>> superproject push to occur first; I would want it to occur last after
>>> the submodules have been successfully pushed.
>>
>> [alias]
>>            recurse-post = !sh -c \"git submodule foreach --recursive --post-order $@ && $@\"
>> ;-)
>>
>>> I agree this should go in some other commit, but I do not think it is
>>> so trivial it should never be considered as a feature for git.  That's
>>> all I'm trying to say.
>>
>> I am not against adding such a functionality to Git, I'm just not
>> convinced "git submodule foreach" is the right command for that. I
>> suspect the "git for-each-repo" Lars proposed earlier this year might
>> be a better choice, as that could also recurse into other repos which
>> aren't registered as submodules. And a "for-each-repo" to me looks
>> like a command which could include the superproject too (at least when
>> told to do so with an option).
>>
>
> Here are the aliases I am using:
>
> [alias]
> 	recurse = !sh -c \"$@ && git submodule foreach --recursive $@\"
> 	recurse-post = !sh -c \"git submodule foreach --recursive --post-order $@ && $@\"
> 	fer = !sh -c \"eval \\\"$@\\\" && git submodule foreach --recursive \\\"$@\\\"\"
> 	ferpo = !sh -c \"git submodule foreach --recursive --post-order \\\"$@\\\" && eval \\\"$@\\\"\"
> 	fers = !sh -c \"eval '$@' && git submodule foreach --recursive '$@'\"
> 	ferpos = !sh -c \"git submodule foreach --recursive --post-order '$@' && eval '$@'\"
>
> And these are the results I get with the following example:
>
> $ cmd="echo \"'ello world: \$PWD\""
> $ eval "$cmd"
> 'ello world: /tmp/a
> $ git submodule foreach --recursive "$cmd"
> Entering 'b'
> 'ello world: /tmp/a/b
> Entering 'b/d'
> 'ello world: /tmp/a/b/d
> Entering 'c'
> 'ello world: /tmp/a/c
> $ git submodule foreach --recursive --post-order "$cmd" "$cmd"
> Entering 'b'
> 'ello world: /tmp/a/b
> Entering 'b/d'
> 'ello world: /tmp/a/b/d
> Exiting 'b/d'
> 'ello world: /tmp/a/b/d
> Exiting 'b'
> 'ello world: /tmp/a/b
> Entering 'c'
> 'ello world: /tmp/a/c
> Exiting 'c'
> 'ello world: /tmp/a/c
> $ git recurse "$cmd"
> 'ello world: /tmp/a
> Entering 'b'
> /home/eacousineau/local/lib/git/libexec/git-core/git-submodule: 1: eval: Syntax error: Unterminated quoted string
> Stopping at 'b'; script returned non-zero status.
> $ git recurse-post "$cmd"
> Entering 'b'
> /home/eacousineau/local/lib/git/libexec/git-core/git-submodule: 1: eval: Syntax error: Unterminated quoted string
> Stopping at 'b'; script returned non-zero status.
> $ git fer "$cmd"
> ello world: /tmp/a
> Entering 'b'
> ello world: /tmp/a
> Entering 'b/d'
> ello world: /tmp/a
> Entering 'c'
> ello world: /tmp/a
> $ git ferpo "$cmd"
> Entering 'b'
> /home/eacousineau/local/lib/git/libexec/git-core/git-submodule: 1: eval: world:: not found
> Stopping at 'b'; script returned non-zero status.
> Stopping at 'b'; script returned non-zero status.
> $ git fers "$cmd"
> ello world: /tmp/a' && git submodule foreach --recursive 'echo ello world: /tmp/a
> $ git ferpos "$cmd"
> Entering 'b'
> /home/eacousineau/local/lib/git/libexec/git-core/git-submodule: 1: eval: Syntax error: Unterminated quoted string
> Stopping at 'b'; script returned non-zero status.
>
> The problem is trying to escape with double-quotes, where the single-quotes are evaluated
> as a shell token thing and not as a string argument, versus single-quotes, where you cannot (easily) escape single
> quotes inside of it (though please correct me if I'm wrong!).
> It seems the best solution would be to have it as a script to allow recursion to occur in the scope of one script,
> like submodule foreach.
>
> I understand now why it does not fit in the scope of 'git submodule', though, so I could implement it as a *very*
> lightweight stand-in for Lars's "git for-each-repo" via some copy-and-paste :P
>
> - Eric
>

Put together a script with the --include-super functionality, named it 'git-fer.sh' to start. Posted as a Gist: https://gist.github.com/eacousineau/5243161

That test case:

$ git-fer --include-super --recursive --post-order "$cmd" "$cmd" Entering supermodule 'a' 'ello world: /tmp/a Entering 'b' 'ello world: /tmp/a/b Entering 'b/d' 'ello world: /tmp/a/b/d Exiting 'b/d' 'ello world: /tmp/a/b/d Exiting 'b' 'ello world: /tmp/a/b Entering 'c' 'ello world: /tmp/a/c Exiting 'c' 'ello world: /tmp/a/c Exiting supermodule 'a' 'ello world: /tmp/a

Previous: Eric CousineauNext: Junio C Hamano
Message 22 of 25 in “Changing submodule foreach --recursive to be depth-first, --parent option to execute command in supermodule as well”
  1. Changing submodule foreach --recursive to be depth-first, --parent option to execute command in supermodule as wellEric Cousineau, Mar 4, 2013
  2. Jens LehmannMar 4, 2013
  3. Junio C HamanoMar 4, 2013
  4. Eric CousineauMar 5, 2013
  5. Heiko VoigtMar 5, 2013
  6. Junio C HamanoMar 5, 2013
  7. Eric CousineauMar 5, 2013
  8. Junio C HamanoMar 5, 2013
  9. Jens LehmannMar 5, 2013
  10. Phil HordMar 5, 2013
  11. Jens LehmannMar 9, 2013
  12. Heiko VoigtMar 11, 2013
  13. Phil HordMar 12, 2013
  14. Eric CousineauMar 14, 2013
  15. Jens LehmannMar 18, 2013
  16. Eric CousineauMar 26, 2013
  17. Jens LehmannApr 2, 2013
  18. submodule foreach: Added in --post-order=<command> and adjusted code per Jens Lehmann's suggestionseacousineau, Apr 13, 2013
  19. Jens LehmannApr 14, 2013
  20. Jens LehmannMar 18, 2013
  21. Eric CousineauMar 26, 2013
  22. Eric CousineauMar 26, 2013
  23. Junio C HamanoMar 26, 2013
  24. Junio C HamanoMar 26, 2013
  25. Eric CousineauApr 13, 2013

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.