Working with git submodules recursively

Git submodules are a relatively decent way to compose multiple source trees together, but they definitely fall short in a number of areas (which others have discussed at length elsewhere). One thing that immediately irritated me was that there is no way to recursively update, commit, push, etc., across all of one's project's submodules. This is something I ran into immediately upon moving to git from svn some months back, and it almost scared me away from git (we used a lot of svn:externals, and now a lot of git submodules).

Thankfully, the raw materials are there in git to work around this. (I've since noticed a bunch of other attempts to do similar things, but they all seem way more complicated than my approach…maybe it's the perl? ;-))

Here's the script we use for operating over git submodules recursively,

[sourcecode lang="bash"] #!/bin/sh

case "$1" in "init") CMD="submodule update –init" ;; ) CMD="$" ;; esac

git $CMD git submodule foreach "$0" $CMD [/sourcecode]

Throw that into your $PATH (I trim the .sh), chmod +x, and git submodules become pretty pleasant to work with. All this is doing is applying whatever arguments you would otherwise provide to git within each submodule, and their submodules, etc., all the way down. The one special invocation, git-submodule-recur init, just executes git submodule update --init in all submodules.

So, want to get the status of your current working directory, and all submodules? git-submodule-recur status Want to commit all modifications in cwd and all submodules? git-submodule-recur commit -a -m "some comment" Want to push all commits? git-submodule-recur push You get the picture.

This script has saved me a ton of typing over the past months. Hopefully, it finds a good home elsewhere, too.

Note: Starting in git 1.6.5, git submodule will grow a –recursive option for the foreach, update and status commands. That's very helpful for the most common actions (and critical for building projects that have submodules in CI containers like hudson), but git-submodule-recur definitely still has a place IMO, especially for pushing.

Update 2009/09/28: I tweaked the git-submodule-recur script to quote the path to the script ("$0" instead of $0); this became necessary when I dropped the script into C:\Program Files\Git\bin in our Windows-hosted Hudson environment.