Propagating GIT commands to its submodules

GIT submodules is an idea (of many) that actually played an extremely important role in me moving to GIT. As a new user I started playing around with GIT and I noticed that GIT commands executed on the parent module is not propagated to the child modules. In some use cases it would be extremely useful (at least for me) to be able to be propagate a command from the master module to all its child at all depth. I wrote this bash shell script to simply propagate commands from parent to its child. To use this script you can simply do the following (I am assuming that the TXT will have the name git-modules and will be an executable in $PATH):
for: git-pull
do: git-modules pull

for: git-status
do: git-modules status

for: git-commit -a -m "This is a test commit"
do: git-modules commit -a -m "This is a test commit"

for: git-checkout master
do: git-modules checkout master
Basically any git-X command can be simply be done as "git-modules X args-as-usual".

I would really appreciate/welcome criticism, feedback and addition to the script. I will be publishing it to the repo.or.cz tomorrow after a little bit more testing.

13 comments:

  1. Just a clarification that "child" in the post refers to the submodules of the current module

    ReplyDelete
  2. I have committed the project ahead of schedule. It can be found as here.

    ReplyDelete
  3. I have made some more modification to the script and it is available in the git repo

    ReplyDelete
  4. Looks nice! Small, simple yet flexible.

    A couple of small things - I think in the normal use case of submodules, it is usual to want to recursive commit - at least with the same commit message. I like to commit in the submodule, then push them, so that I know that the supermodule never refers to a commit which is not published on the listed URL.

    Finally, I do not think it would take much to brush this up for a contrib/ command to widen its user base.

    ReplyDelete
  5. Nice.

    I simply have to wonder why this is a separate "git module" command and not a new set of subcommands to "git submodule" command, though.

    I have to mildly disagree with mugwump. If your submodule houses a common library, and your supermodule (or another submodule) is an application that uses the library, you do not want to have the same commit message when you make an infrastructure enhancements in the former to support a change in the latter. The commit for the library is to enhance some aspects of it for general uses, and the commit for the application records a change that happens to be the first use of the enhancement. The creation of these changes are logically separate events (the only relationship between them is that the former can never come before the latter). It is possible that the library change and the application change are both very isolated and the library change is a special purpose hack to support only that change in the application and no other users, in which case "recursive and with the same commit message" may be useful, but from the general project organization point of view, it is a degenerated special case.

    If the library change is more involved, it would be done in several logical steps and only after all of them are finished, the history of the application (either the supermodule or a sibling submodule) can use it. You cannot and do not want to use recursive behaviour to record such a general case anyway.

    ReplyDelete
  6. Actually I agree with both of you. But a general norm that I had been following while working on a project is before every checkin (commit) I update and merge the code bases. Now at least for the update part I would actually want to update all the modules at once rather than one at a time. Again though the commit messages might be different I want to push all at once or want I want to see the status, i.e. changes at once; for those kind of scenario something recursive will come in handy. That is what I originally intended the script for - simple recursion. Not to mention that the usual commands that is available currently would also be available, so based on the use case the user can choose which one they want.

    About why having a separate command, I emailed the script to the GIT mailing list but I did not receive any response as of now, I am eagerly waiting to see the developers comment on it. If all agree I would be most grateful to merge it with git-submodules command.

    ReplyDelete
  7. Heh, gitster, upon re-reading this article I noticed that I had accidentally dropped out the "not" from that sentence! Yes, I meant in general you don't want recursive commit.

    ReplyDelete
  8. There was a small bug with passing command recursively from traverseModule, fixed that and converted the bash script to sh script. The GIT repo contains the latest scripts.

    ReplyDelete
  9. I just added another feature in the script - if the git-submodule init and update is not called on the module being recursed on currently the script will call it. Check the repo for the update

    ReplyDelete
  10. Updated git-clone with -w option to init and update submodule during cloning. It is in the repo now.
    Submitted these two features as patches to the mailing list

    ReplyDelete
  11. The module's path is not necessarily a direct subdirectory. I.e. it is not correct to just "cd .." to get back where one started from.

    The following traverseModule function fixes this issue:

    function traverseModule() {
    echo Traversing module $1 for command \"$2\"
    local bakpwd=`pwd`
    cd $1
    eval $2
    if [ -f .gitmodules ]; then
    for mod_path in `grep "path =" .gitmodules | awk '{print $3}'`; do
    traverseModule $mod_path $2
    done
    fi
    cd $bakpwd
    }

    ReplyDelete
  12. Thanks for the hint, but in reality this code snippet is no longer in use (even by me). Please check the git repo for details. Thank you once again.

    ReplyDelete
  13. Indeed. I thought you did... but could not find the url before. Downloaded it now. Thanks.

    ReplyDelete

Search