Pull/update all repos in a path: git update.sh
Jump to navigation
Jump to search
#!/bin/bash
# 1. Secure temporary file handling
JOBLOG=$(mktemp)
trap '[ -n "${FAILURES:-}" ] || rm -f "$JOBLOG"' EXIT
# Prevent terminal-based password prompts from freezing background parallel tasks
export GIT_TERMINAL_PROMPT=0
# 2. Define and export the update task
sync_repo() {
# Fast, zero-fork path cleaning using Bash parameter expansion
local repo="${1%/.git}"
# ANSI Colors for terminal output
local CYAN='\033[1;36m'
local GREEN='\033[1;32m'
local RED='\033[1;31m'
local NC='\033[0m' # No Color
# Uses your default system HTTPS/Credential helper settings natively
local fetch_out
fetch_out=$(git -C "$repo" fetch --all 2>&1)
if [ $? -ne 0 ]; then
printf "${CYAN}%s${NC} ${RED}FETCH FAILED${NC}\n" "$repo"
echo "$fetch_out" >&2
return 1
fi
local pull_out
local status
pull_out=$(git -C "$repo" pull --ff-only --recurse-submodules 2>&1)
status=$?
# Extract the last non-empty line of output safely
local summary
summary=$(awk 'NF {last=$0} END {print last}' <<< "$pull_out")
# Clean single-line formatting separated by a single space
if [ $status -eq 0 ]; then
printf "${CYAN}%s${NC} ${GREEN}%s${NC}\n" "$repo" "$summary"
else
printf "${CYAN}%s${NC} ${RED}%s${NC}\n" "$repo" "$summary"
echo "$pull_out" >&2
return 1
fi
}
export -f sync_repo
# 3. Find and update repos in parallel (Single line, no backslashes)
find . -name ".git" -type d -prune -print0 | parallel -0 -j 8 --group --joblog "$JOBLOG" sync_repo
# 4. Parse failures and exit with the correct status code
FAILURES=$(awk -F'\t' 'NR>1 && $7!=0 {sub(/^sync_repo /, "", $9); sub(/\/\.git$/, "", $9); print $9}' "$JOBLOG")
echo ""
if [ -n "$FAILURES" ]; then
printf "\033[1;31mFailures occurred in the following repositories:\033[0m\n"
printf "%s\n" "$FAILURES"
printf "\n\033[1;33mDebug log preserved at:\033[0m %s\n" "$JOBLOG"
exit 1
else
printf "\033[1;32mAll repositories synced successfully!\033[0m\n"
exit 0
fi
Basic One liner[edit]
Pull all repos in a path, including subdirectories:
find . -name ".git" -type d | sed 's/\/.git//' | parallel 'echo -e "\n=== {} ===" && git -C {} pull 2>&1'
Related[edit]
git_clone.sh-prunegit-auto-fetch- from the remote, but no such ref was fetched.
- create mode 100644
- delete mode 100644
- FETCH FAILED
- error: Your local changes to the following files would be overwritten by merge:
- from the remote, but no such ref was fetched.
- rename
See also[edit]
Advertising: