DEV Community

Pato
Pato

Posted on • Edited on • Originally published at gabac.blog

Git pull multiple repositories at once

Update: I wrote about another approach to achieve this and some extras, with git submodules. You can find it here here.

I usually work with many repos at the same time and generally group them within a same directory, named after the company.

In example, if I'm working for "Great Employer INC." I'll have a directory probably named greatemployerinc and one directory for each repo I work within. Something like:

greatemployerinc
├── greatemployerinc-web
├── greatemployerinc-auth
├── greatemployerinc-core-service
├── greatemployerinc-email-service
├── ...more repos
└── greatemployerinc-gateway

Instead of navigating each one of them with cd and then manually run git pull branch, I came out with the following command that I run from greatemployerinc -the repos containing directory.

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

It will find any subdirectory in the current one (greatemployerinc), without going deeper than the first level (delimited by mindepth 1 and maxdepth 1) and execute a git pull in the corresponding git dir (if its a repo).

If you want to see more on the git -C option, you can check this post on SO

Keep in mind it will run a git pull on the current branch that each repository is actually stepping on. Also, consider the pull might fail if you have pending changes (it will be shown on the console output, anyway) and you might need to handle those cases manually, or considering adding an --autostash option to the provided command.

Wait, I can't memorize that command!

Then you and I have something in common :)

To avoid memorizing it, I created an alias. If you are working with ZSH you can just add this line to your ~/.zshrc file

alias multipull="find . -mindepth 1 -maxdepth 1 -type d -print -exec git -C {} pull \;"

Then close your current terminal and open a new one (so the changes on .zshrc take effect), go to your equivalent greatemployerinc directory and do:

multipull

And drink your favorite infusion while your repos pull from remote :)

Conclusion

So, we created a quick small command to run a pull in multiple repos at once, then we created an alias for it so it is more easy to run later.

If you are willing to take it further, you can tweak it a little bit around if you want to customize the branch you pull from/into, run a different command, or try and make it run in parallel.

Updates

If you are interested on "resourcing" your terminal without closing/opening it, see this comment from JPBlancoDB

If you are interested on more complex scenarios, you can use a tool like myrepos just like Caleb Maclennan points out in this comment

Top comments (9)

Collapse
 
alerque profile image
Caleb Maclennan • Edited

There is a solid little tool build specifically to handle this sort of thing called myrepos that not only handles the simple use case you outline more elegantly but allows for a lot more flexibility. Even if most repos cat be pulled the same way, you'll run into cases where one needs extra options, or one that you want to fetch but not pull by default, or whatever. While having sane defaults for operations like "pull" it allows you to override them on a per-repo basis (or even per host, or whatever) and even composes your own sequences. You can mix and match VCS systems too, not just git. Finally it handles parallel execution which can greatly speed up the task when updating a lot of repos because you don't want to wait on local processing before getting busy on the network fetch for the next one.

$ cd greatemployerinc
$ mr pull
Enter fullscreen mode Exit fullscreen mode

This also makes "sets" of repositories portable. You can keep a configuration that has various groups and easily clone them all at once when you need them on a new machine.

Collapse
 
rmpato profile image
Pato

Hi Caleb! Thank you for sharing this! I'll add it to the post as an alternative for more complex/specific scenarios :)

Collapse
 
jpblancodb profile image
JPBlancoDB

Great tip! Thanks!

I also have as an alias (bash):

alias refreshBash="source /home/jp/.bash_profile"

With this, you avoid closing the terminal for reloading the configuration.

Thanks again! Already added this multipull as an alias 💪.

Collapse
 
rmpato profile image
Pato

Awesome!

Thanks for sharing, I'll do the same for my ZSH 🤗🤗

I might update the post later to add yours as a tip!

Collapse
 
pkwhaley profile image
Pete (he/him)

I stumbled on this old topic because I was playing with a few solutions for it today.

I ended up using a nice git-alias to achieve this result which also lets you pass any other commands to all subdirecty repos:

git config --global alias.all '!f() { ls -R -d */.git | xargs -I{} bash -c "echo {} && git -C {}/../ $1"; }; f'
Enter fullscreen mode Exit fullscreen mode

This lets you do commands like:

git all pull
git all checkout <branch>
git all status
etc...
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mani0811 profile image
Mani Shankar

thanks . git all branch delete is not working .

Collapse
 
ianwijma profile image
Ian Wijma

Sound similar to submodules from git.
git.wiki.kernel.org/index.php/GitS...

Maybe that is also usefully material. 😁

Collapse
 
rmpato profile image
Pato

Hi Ian! Thanks for sharing :)

Also, if you are interested into git submodules I do recommend you this post dev.to/omrilotan/working-with-git-...

Collapse
 
kojix2 profile image
kojix2

This command is so useful that I made it into a RubyGem.