From Chaos to Control: My Git Pull Automation Story
Automation

From Chaos to Control: My Git Pull Automation Story

By Hany Mamdouh | CEO | AtenTEC5 min read

From Chaos to Control: My Git Pull Automation Story

Introduction

Managing enterprise-scale projects comes with unexpected challenges.

One of the biggest yet most underestimated problems we faced was:

👉 Synchronizing many Git repositories across multiple environments.

In our case, over 200 repositories are split into layers — core drivers, applications, presentation. Each repository is tied to specific branches for Pilot Testing and Production (among other branches), used for CI/CD pipelines and Docker builds.

As the engineer responsible for overseeing all production branches, and working across two computers (home and office), I needed a faster, safer, and cleaner way to pull updates across all repos without mistakes.

This is the story of how I solved it.

The Problem

When you work with this number of repositories:

  • Manual pulling is impossible: You simply can't cd repo && git pull 200 times.
  • Human errors happen: Pulling the wrong branch, missing uncommitted changes, etc.
  • Branch validations are critical: Our workflows demand that each repository must have matching Pilot Test and Production branches.
  • Speed and clarity are needed: I wanted something I could trust without second-guessing every step.

My Solution: A Simple but Powerful Bash Script

Instead of complex orchestration tools, I created a simple Bash script that:

  • Validates all repositories first:
    • Remote branch existence.
    • No local uncommitted changes.
  • Executes pulls only when validation passes.
  • Silent operations for clean outputs.
  • Progress indicators for a pleasant big-screen experience.

Why validation first?

Because in enterprise production flows, you want to guarantee that no repo pulls anything unless all conditions are perfect.

One small mistake can propagate wrong builds and delays.

The Script Overview

# 1. Configures repositories and target branch
# 2. Validates:
#    - Branch existence (using git ls-remote)
#    - Clean working tree (no uncommitted changes)
# 3. Pulls latest updates quietly
# 4. Checks out the correct branch
# 5. Displays friendly progress counters

Key UX Enhancements

Even though it’s "just a script," I like my scripts to be appealing:

  • Clear separation between Validation and Execution phases.
  • Fatal early exits on any failure (no partial operations).
  • Unicode icons and visual separators for better readability.
  • Progress counters like [12/200] during execution — critical for multi-minute operations.
  • Silent Git operations (--quiet, suppressing stdout spam).

These little UX touches matter especially when you're dealing with dozens or hundreds of repositories.

Why Not Use Big Tools?

You might ask:

"Why not use tools like Git Submodules, Monorepos, Repo tools, or automation frameworks?"

Simple:

  • We intentionally separate our repos for modular scaling.
  • Our team structure, CI/CD pipelines, and Docker architecture are built around independent repos.
  • Adding heavyweight tooling would create more friction than it solves.
  • This script is fully controlled, understood, and owned by us — no hidden complexities.

Sometimes, small elegant tools beat big complex ones.

The full script

Here is the full script.

#!/bin/bash
 
# ------------------------------
#  Configurations
# ------------------------------
 
# define rpositories here
declare -a repos=(
  "~/repo/project1/repo1"
  "~/repo/project1/repo2"
  "~/repo/project1/repo2"
)
 
branch="$1"
 
# ------------------------------
#  Helpers
# ------------------------------
 
print_separator() {
  echo -e "------------------------------------------------------------"
}
 
fatal() {
  echo -e "\n❌ $1"
  exit 1
}
 
ok() {
  echo -e "\n✅ $1"
}
 
# ------------------------------
#  Start
# ------------------------------
 
clear
 
echo "🔍 Git Multi-Repo Puller"
print_separator
 
# ------------------------------
#  Argument Check
# ------------------------------
if [[ -z "$branch" ]]; then
  fatal "Branch argument is missing. Usage: $0 <branch-name>"
fi
 
echo "Target Branch: $branch"
print_separator
 
# ------------------------------
#  Validation Phase
# ------------------------------
 
echo "📋 Starting Validation Phase..."
 
for repo in "${repos[@]}"; do
  echo "Checking repo: $repo ..."
 
  # Check remote branch exists
  if ! git -C "$repo" ls-remote --heads origin "$branch" | grep -q "$branch"; then
    fatal "Repo [$repo] has no remote branch [$branch]. Aborting!"
  fi
 
  # Check no local uncommitted changes
  if [[ ! $(git -C "$repo" status --porcelain | wc -l) == "0" ]]; then
    fatal "Repo [$repo] has uncommitted changes. Aborting!"
  fi
done
 
ok "Validation successful. All repositories are clean and ready."
 
print_separator
 
# ------------------------------
#  Execution Phase
# ------------------------------
 
echo "🚀 Starting Execution Phase (Pull + Checkout)..."
print_separator
 
repo_count=${#repos[@]}
current=1
 
for repo in "${repos[@]}"; do
  echo "[$current/$repo_count] Processing: $repo ..."
  git -C "$repo" pull --quiet
  git -C "$repo" checkout "$branch" --quiet > /dev/null 2>&1
  ((current++))
done
 
print_separator
ok "All repositories pulled and switched to [$branch] successfully!"
echo "🌟 Done."

You can check my Github account for more scripts and projects.

hanymamdouh82

Final Thoughts

This tiny project reminded me of a big principle:

Even simple problems deserve professional solutions.

When you care about clarity, validation, UX, and safety — even a small Bash script can feel like a well-designed product.

If you're managing dozens or hundreds of repositories, don't settle for manual chaos.

👉 Automate it. Polish it. Own it.


I'd love to hear:

  • How do you manage multi-repo projects?
  • Have you built your own tools too?
  • What other internal pains would you love to automate?

Feel free to connect, share your thoughts, or suggest improvements.

Category

Automation

Tags

Programming
DevOps
CI/CD Pipeline
Source Control
Bash Scripting
Hany Mamdouh | CEO | AtenTEC

Hany Mamdouh | CEO | AtenTEC

As the Co-Founder and CEO of Anchornize and CEO of AtenTEC, I bring over 20 years of experience in software engineering, solution architecture, and business management. I specialize in leading enterprise-level software projects, developing innovative solutions, and aligning technology with business objectives to drive growth and efficiency.

Related Articles

CI/CD for Google Cloud Functions in a mono repo
5 min read

CI/CD for Google Cloud Functions in a mono repo

This article details a solution for implementing a CI/CD pipeline for Google Cloud Functions within a single mono-repository. It addresses the challenge of efficiently deploying over 500 functions by using a GitHub Actions workflow. The solution is designed to automatically identify and deploy only the changed functions after a code push, which optimizes build time and resource usage. The guide walks through structuring the mono-repo, building the workflow trigger, identifying changed functions with git diff, and deploying them iteratively using a GitHub Actions matrix.

Mastering Modern Authentication: A Guide to Secure Communication
5 min read

Mastering Modern Authentication: A Guide to Secure Communication

This article provides a practical guide to modern authentication patterns using OIDC and OAuth 2.0. Through three easy-to-understand sequence diagrams, it visualizes the secure flows for backend-to-backend communication, frontend-to-backend user logins with stateful sessions, and a combined scenario where a backend service makes a B2B call to fulfill a frontend request. It explains the core concepts of token exchange, session management, and role-based access control (RBAC), making these complex interactions accessible to developers and system architects.

Background

Stay in the loop

Need to know more? book a consultation meeting now