Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save omaralamoudi/6d5857d398216a4b1c32ec2c766d17cd to your computer and use it in GitHub Desktop.
Save omaralamoudi/6d5857d398216a4b1c32ec2c766d17cd to your computer and use it in GitHub Desktop.
Git checkout or create new branch recursively in repo and submodules

Git checkout or create new branch recursively in repo and submodules

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.

What if you want to perform a task repeatedly in all submodules?

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.

What if your submodules have their own submodules?

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:

  1. Peforming a task recursively that accespts input arguments
  2. Specializing that task to checkout a or create it if it doesn't exist

1. Peforming a task recursively that accespts input arguments

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.

2. Specializing that task to checkout a or create it if it doesn't exist

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment