If you are using submodules in a git repo, you might find yourself sometimes wanting to execute a command recursively in the primary/parent repo as well as all submoduls. Well, I found myself in that position, and I'm writing this for my future self.
The most basic approach to this is to use git submodule foreach <command>
, where <command>
can be any git command, or a shell command including commands such as git status .
or git checkout main
This basically loops through all submodules and performs the command specified, but it does not execute this command in the root repo.
Well, that is luckely easy too. Simply add the keywoard --recursive
as following:
git submodule foreach --recursive <command>
What if you want to checkout or create a new branch in the primary/parent repo and all submodules recursively?
Well, lets break this down into two parts:
- Peforming a task recursively that accespts input arguments
- Specializing that task to checkout a or create it if it doesn't exist
Lets create a git
alias that accepts positional arguments as such:
git config --global alias.forall "!f(){ git submodule foreach --recursive git $@ && echo \"Entering 'root'\" && git $@; }; f"
Lets breakdown the previous command:
git config --global alias.forall
: creates a git alias with a global scope called forall
.
!
: depands that the execution of the command is done in the shell, not as a git
command
f(){ git submodule foreach --recursive git $@ && echo \"Entering 'root'\" && git $@; };
: defines a function f
that passes all input arguments $@
to two subcommands git submodule foreach --recursive git $@
, and git $@
where the former pefroms the command git $@
recursively inside all submodules and their submodues, and git $@
peforms the command in the root repo. In addition, there is a third command echo \"Entering 'root'\"
this command simply prints out a line for visual clarity.
Now that we have a way of executing commands with positional arguments in the root repo as well as the submodules, we can use the following command to checkout a or create it if it doesn't exit
git forall checkout -b <new-branch>
There remains to be a problem, if the branch <new-branch>
exists in any of the submodules, this will produce an error and it won't work.
Further tweeking is needed.
The following links: 1, 2, and 3 were helpful in creating the provided solution