One of the important elements of efficient software development is to keep boring tasks at bay.
In this post, I describe the process of creating a bash script for keeping local git repositories up to date with the remote repositories with a help of ChatGPT.
My initial request looked like this:
write a bash script which goes to every subfolder and if it contains git repo checks out master branch and pulls. it should also print out if it's been done successfully or failed for every folder
Chat gave me a decent answer with comments for every command
First attempt
#!/bin/bash
# Iterate over all subdirectories
for d in */ ; do
# Enter the subdirectory
cd "$d"
# Check if it is a git repository
if git rev-parse --git-dir > /dev/null 2>&1; then
# Check out the master branch
git checkout master
# Pull the latest changes
if git pull; then
# Print success message
echo "Successfully updated $d"
else
# Print error message
echo "Failed to update $d"
fi
fi
# Return to the parent directory
cd ..
done
After a whole bunch of clarification which includes:
- before git pull let’s check if there are changes and print it out
- not changes to be pulled, but rather working directory changes
- check for working directory changes first and then checkout and pull
Intermediate result
#!/bin/bash
# Iterate over all subdirectories
for d in */ ; do
# Enter the subdirectory
cd "$d"
# Check if it is a git repository
if git rev-parse --git-dir > /dev/null 2>&1; then
# Check if there are any changes in the working directory
if git diff-index --quiet HEAD; then
# No changes, so check out the master branch
git checkout master
# Pull the latest changes
if git pull; then
# Print success message
echo "Successfully updated $d"
else
# Print error message
echo "Failed to update $d"
fi
else
# Changes in the working directory, so don't pull
echo "Working directory changes in $d, skipping pull"
fi
fi
# Return to the parent directory
cd ..
done
And the final touch: let’s do some output formatting and coloring
modify the output: success - green color "folder name, master branch", working directory changes - yellow color text "folder name, branch name, number of files with changes", failed for any other reason - red color text "folder, branch name"
Final result
#!/bin/bash
# Function to print the branch name in green
print_green() {
printf "\033[32m%s\033[0m\n" "$1"
}
# Function to print the branch name in yellow
print_yellow() {
printf "\033[33m%s\033[0m\n" "$1"
}
# Function to print the branch name in red
print_red() {
printf "\033[31m%s\033[0m\n" "$1"
}
# Iterate over all subdirectories
for d in */ ; do
# Enter the subdirectory
cd "$d"
# Check if it is a git repository
if git rev-parse --git-dir > /dev/null 2>&1; then
# Get the current branch name
branch=$(git rev-parse --abbrev-ref HEAD)
# Check if there are any changes in the working directory
if git diff-index --quiet HEAD; then
# No changes, so check out the master branch if not already on it
if [ "$branch" != "master" ]; then
git checkout master > /dev/null
fi
# Pull the latest changes
if git pull > /dev/null; then
# Print success message in green
print_green "Successfully updated $d ($branch)"
else
# Print error message in red
print_red "Failed to update $d ($branch)"
fi
else
# Changes in the working directory, so don't pull
# Get the number of changed files
num_changes=$(git diff --name-only | wc -l)
# Print warning message in yellow
print_yellow "Working directory changes in $d ($branch, $num_changes file(s) changed)"
fi
fi
# Return to the parent directory
cd ..
done
The result of the script execution looks like the following
The repository names and branches are redacted.