I'm trying to write a script that I can add to later on. Basically, I have a collection of git repos all over my home directory. I'd like to keep a master list of their locations and then have a script run through them all and run a git up command or git pull or something.

I'm tired of having to cd into everything individually to get it to update. I'd like to do it all at once, but there's no rhyme or reason to their locations, and I'd prefer not to restructure my home folder tree just to accommodate some scripting action.

I'm more than happy to have this like a config file where I can simply append more directories to the beginning of the file as needed over time.


Here's where I'm at:

cd ;

for repo in $dir1, $dir2;
  cd "$repo"
  git up  
cd $CWD

Oh, and I'm using ZSH, not bash...


2 Answers 2

# This will attempt to do a `git pull` in any directories found in the
# present working directory.

for d in *; do
    if [[ -d "$d"/.git ]]; then
        ( cd $d; git pull )
  • 2
    Why not just for d in */; do [[ -d "$d/.git" ]] && ( cd $d && git pull); done?
    – terdon
    Dec 7, 2016 at 17:06
  • add a cd - after the git pull ?
    – magor
    Dec 7, 2016 at 17:08
  • "...there's no rhyme or reason to their locations..." ;) I suspect looking at git's --git-dir or -C options would be useful.
    – John N
    Dec 7, 2016 at 17:08
  • 1
    @mazs no need, that's why DopeGhoti is using the (subshell).
    – terdon
    Dec 7, 2016 at 17:11
  • 1
    for d in $(find $HOME/ -type d -name .git); do ( cd "$d"/..; git pull ); done.
    – DopeGhoti
    Dec 7, 2016 at 17:16

You do not actually have to change directory into a git repository in order to run a command with git. You can pass the working directory to git with -C path.

If you want to keep a list of repositories, I would suggest using an array:

"$HOME/somedir/with space/repo2"

for repo in $repos; do
    git -C $repo $@

If you put this in a script, say with tha name multigit, you can run any git command on it, as the arguments are passad withing $@. For example multigit pull.

If you do not care about configuring a list of repositories, you can even get zsh to find them all for you:

for repo in **/.git(/N); do
    git -C ${repo:h} $@

**/.git(/N) will recursively search for any directory named .git and ${repo:h} will remove the last element of a path, in this case .git, leaving you with the paths to the repositories.

Bonus: you can even get Tab-completion for your new command:

compdef '_dispatch git git' multigit
  • Whoa that's sweet! Dec 13, 2016 at 12:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .