Jorisvandijk.com

Living on Linux

Managing multiple git repositories on my system

I have a couple of git repositories on my system, which are used to back up all sorts of things to Gitlab. I have a documents one, a notes one, obviously my dotfiles and some school stuff. Keeping track of all of these is a bit of a pain, as you have to cd into each root git folder, check if there's been a change and if so, commit and push it. Ideally you're on top of things and remember to commit whenever you make a change and push those when it's convenient, but I find I usually lose track of these things. I need a way to have an overview of all, so Bash script time.

This is the script I use. It is a constantly evolving thing, so it may look completely different in the future. For now though, this does the job for me. A large part of this was taken from Matt Zabriskie's Github Gist.

#!/usr/bin/env bash

# UpdateRepositories 2.2
# Checks repositories for updates and enables doing them
# Dependencies: git, kitty
#
# By Joris van Dijk | Jorisvandijk.com
# Licensed under the GNU General Public License v3.0

dir="$HOME/.gitrepositories/"
term="kitty --class floatterm -e "
script="UpdateRepositories"

changes(){
# No directory has been provided, use current
if [ -z "$dir" ]
then
dir="`pwd`"
fi

# Make sure directory ends with "/"
if [[ $dir != */ ]]
then
dir="$dir/*"
else
dir="$dir*"
fi

# Loop all sub-directories
for f in $dir
do
# Only interested in directories
[ -d "${f}" ] || continue

echo -en "\033[0;35m"
echo "${f}"
echo -en "\033[0m"

# Check if directory is a git repository
if [ -d "$f/.git" ]
then
mod=0
cd $f

# Check for modified files
if [ $(git status | grep modified -c) -ne 0 ]
then
mod=1
echo -en "\033[0;31m"
echo "Modified files"
echo -en "\033[0m"
fi

# Check for untracked files
if [ $(git status | grep Untracked -c) -ne 0 ]
then
mod=1
echo -en "\033[0;31m"
echo "Untracked files"
echo -en "\033[0m"
fi

# Check for unpushed changes
if [ $(git status | grep 'Your branch is ahead' -c) -ne 0 ]
then
mod=1
echo -en "\033[0;31m"
echo "Unpushed commit"
echo -en "\033[0m"
fi

# Check if everything is peachy keen
if [ $mod -eq 0 ]
then
echo "Nothing to commit"
fi

cd ../
else
echo "Not a git repository"
fi

echo
done
}

choices(){
echo -e "Please select a repository.\n"
PS3="Enter a number: "

select repo in $(ls -d */| sed 's/.$//')
do
result=$repo
break;
done
}

updates(){
REPO=$(echo $result | sed 's:/*$::')
cd $HOME/.gitrepositories/$REPO
git pull
git add .
git status
echo
read -p "Enter commit message: " MESSAGE
git commit -m"${MESSAGE}"
git push -u origin main
}

anotherupdate() {
echo -n "Update another repository (Y/N)? "
while read -r -n 1 -s answer; do
if [[ $answer = [YyNn] ]]; then
[[ $answer = [Yy] ]] && retval=0
[[ $answer = [Nn] ]] && retval=1
break
fi
done

echo # just a final linefeed, optics...

return $retval
}

changes
choices
updates
if anotherupdate; then
nohup $term $script &>/dev/null 2>&1
else
echo "Exiting."
fi

So the way this script works is it checks the $HOME/.gitrepositories folder. This folder contains symlinks to all the repositories I want to keep track of on my system. When you launch the script it will present you with a list of your repositories and it will show you which has modified or untracked files.

Previous website

Next you type the number corresponding with the repository you'd like to update and the script will show you exactly which files where altered or added. It will then ask for a commit message. Entering this and pressing enter will push the changes to git and the script will ask if you'd like to update another repository.

A couple of things to note. The first three lines of code are important.

This is the location of the folder with the symlinks to your repos:

dir="$HOME/.gitrepositories/"

The following is the terminal being used, the class it is given and the execute flag. I use the floatterm class to have the terminal window float in a set way. This is done through the i3 config file. Note there's a space after the -e:

term="kitty --class floatterm -e "

And the last one is the name of the script as it's saved on your system. If you wanted to rename the script, you have to also alter this line:

script="UpdateRepositories" 

Have fun playing around with the script and if you have improvements, don't hesitate to let me know! And as always, this may not be the most up to date version of this script. For that, head over to my dotfiles.