Git and libgit2

Updating Trees of Git Repositories

Published 2023-03-11.
Time to read: 1 minutes.

This page is part of the git collection.

I need to keep several hundred git repositories up-to-date. I have a directory tree of website repos, and a directory tree of code repos. Updating these trees was tedious until I wrote the initial version of the update script back in 2008.

Environment Variables

My ~/.bashrc script defines two environment variables, each of which point at the root of one of the following directory trees:

sites
Points to the root of the website directory tree
work
Points to the root of the code project tree
~/.bashrc
export sites=/var/www
export work=/var/work

In addition, I define subordinate environment variables for each project in a file called $work/.evars

$work/.evars
export cadenzaHome=$work/cadenzaHome
export cadenzaCode=$cadenzaHome/cadenzaCode
export cadenzaDependencies=$cadenzaCode/cadenzaDependencies
export awslib_scala=$cadenzaDependencies/awslib_scala
export shoppingcart=$cadenzaDependencies/shoppingcart
export clients=$work/clients
export django=$work/django
export msp=$sites/www.mslinn.com
... 

$work/.evars is included by ~/.bashrc

~/.bashrc
export sites=/var/www
export work=/var/work
source $work/.evars

Switching Directories

The above environment variables allow me to easily move to a git project directory without having to remember where it resides on the computer that I am currently using:

Shell
$ cd $clients
$ pwd /var/work/clients

Updating Git Directory Trees

The site and work environment variables are used by the update script:

#!/bin/bash

# Update all git directories below current directory or specified directory
# Skips directories that contain a file called .ignore
# See https://stackoverflow.com/a/61207488/553865

if [ "$( curl -sL -w "%{http_code}\n" https://www.github.com -o /dev/null )" != 200 ]; then
  echo "Cannot connect to GitHub"
  exit 2
fi

HIGHLIGHT="\e[01;34m"
NORMAL='\e[00m'

export PATH=${PATH/':./:'/:}
export PATH=${PATH/':./bin:'/:}
#echo "$PATH"

if [ -z "$1" ]; then
  ROOTS="$sites $work"
else
  ROOTS="$@"
fi

echo "Updating $ROOTS"
DIRS="$( find -L $ROOTS -type d \( -execdir test -e {}/.ignore \; -prune \) -o \( -execdir test -d {}/.git \; -prune -print \) )"

echo -e "${HIGHLIGHT}Scanning ${PWD}${NORMAL}"
for d in $DIRS; do
  cd "$d" > /dev/null || exit 2
  echo -e "\n${HIGHLIGHT}Updating `pwd`$NORMAL"
  git pull
  cd - > /dev/null || exit 3
done

Most of the time I want to update everything in both directory trees, so for that no arguments are required:

Shell
$ update
Updating /var/www /var/work
Updating /var/work/cadenzaHome/cadenzaCode/cadenzaDependencies/awslib_scala
Already up to date.
Updating /var/work/cadenzaHome/cadenzaCode/cadenzaDependencies/shoppingcart Already up to date.
...

It is also possible to update an arbitrary directory tree of git repositories:

Shell
$ update /path/to/another/tree
Updating /path/to/another/tree 
😁

I hope you find the update script as useful as I have!

* indicates a required field.

Please select the following to receive Mike Slinn’s newsletter:

You can unsubscribe at any time by clicking the link in the footer of emails.

Mike Slinn uses Mailchimp as his marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp’s privacy practices.