A new use case for git submodules
Tags: git, tutorial, showdev, productivity
Published: 2020-02-05 17:13:43

---
title: A new use case for git submodules
published: true
description: Treating many repositories as one, with git submodules
tags: git, tutorial, showdev, productivity
---

Git submodules are a gray area to me: not because of how they work, but because of identifying a situation they suit up nicely, and that is, without feeling I'm complicating things unnecessarily. 

Some time ago I wrote [this article in my blog](https://gabac.blog/posts/git-pull-many-repos-at-once/), and also on [dev.to](https://dev.to/rmpato/git-pull-multiple-repositories-at-once-4l68) which is kind of a sloppy solution to a problem that deserved a better one. So, now I've got time to revisit it, and yes: this time we approach with (oh, you got it already!) git submodules!

Now, instead of running this hard to memorize and not so extensible command I came up with before:

```bash
find . -mindepth 1 -maxdepth 1 -type d -print -exec git -C {} pull \;
```

Now, I can just do: 

```bash
git submodules foreach command 
```
Where `command` would be anything we want to run across all the repos.   

So, this post is about solving what was already solved, this time with a better, more extensible approach: 
A simple yet useful approach with submodules.

## Git submodules 

So, this is what we'll be doing:

1. Create a new repo 
2. Add in every repo we want to manage as a submodule
3. Checkout a branch on every submodule/repo - one command!
4. Get the status of each submodule from top-level repo - one command!
5. Check all submodule repos status - one command!
6. Pull changes for every submodule - one command!


Alright then, let's do it!

### Create a new repo
Just cd into a new dir, and init a new repo.

```
mkdir platform-repo && git init
```
### Add every repo you want to control as a submodule
 Repeat this as many times as repos you wish to add. Each repo will be mounted in a new directory (similarly as git clone does).

```
git submodule add repo_url
```

### Checkout a branch on every submodule

Now, we need to point our submodules to a branch. Depending on your git version, by default submodules have a detached head (meaning they don't point to any branch). I'm assuming you would be pointing them  to either `dev` or `master` branch, but you can point them to wichever branch you wish to.
 ```
 git submodule foreach git checkout dev
 ```

### Check the status of the submodules
from the 'top-level' repo, just run: 
 ```
 git status
 ``` 
It will show every submodule and its status. As you work on your submodules, you will see different statuses: new commits (since the moment you add them as submodules), untracked changes (not commited, nor staged), or yet pristine.  
When a submodule shows new commits, it means it has them since the moment you added the submodule to the top-level repo. It works like this, because the top-level repo holds a reference to a commit in the submodule repo, and when it detects newer commits than the one it is holding its reference into, it shows the difference.
If you want it to show no new commits, you just need to create a commit in the top-level repo. You can read more about that [here](https://unix.stackexchange.com/questions/214879/git-submodule-shows-new-commits-submodule-status-says-nothing-to-commit). 
     
### See each submodule status
 To get submodules status as if it were an independant repo, you should:
 ```
 git submodule foreach git status
 ```
 And you are golden.


### Pull changes for every submodule

 ```
 git submodule foreach git pull --rebase --autostash origin branch_name
 ```
 
This way, `--autostash` will assure to add your changes to stash, pull, then rebase on your branch and pop changes out of stash. And all of that automatically, so you don't need to commit or stash your changes manually.   
 This is useful because when running commands with the `git submodule foreach command` expression, if the command exits with an error code, it might cancel the whole foreach chain. This way we ensure it doesn't exit as an error, by reducing chances for failling of the pull.

## Other cases

For any other case, you can always cd into each submodule and see it still is a normal repository. So you can work from there as you usually do. Just keep that in mind when running git submodule foreach commands from the top level repo. I.E not all submodules might be in the same branch, etc.

## Conclusions

Here is another approach to work with many repositories at once. We could reach a similar thing if working with monorepos, but this wasn't an option at the place I was working at the moment I wrote this post. So, I found this approach, which you can maybe think about 'simulating a monorepo'. 

Just by adding a set of repos as submodules, you can work around it nicely. 

---
>You can read in depth about git submodules [here](https://git-scm.com/book/en/v2/Git-Tools-Submodules).

>This post was originally posted [here](https://https://gabac.blog/posts/git-submodules/)