#!/bin/bash set -euo pipefail IFS=$'\n' if [[ $# -lt 3 ]]; then echo "Usage: $0 " exit 1 fi cd "$1" leader="$2" shift 2 followers=( "$@" ) echo "Working directory: $PWD" echo "Leader remote: $leader" echo "Follower remotes: ${followers[*]}" | tr '\n' ' ' echo; echo torify git fetch --prune --multiple "$leader" git fetch --prune --multiple "${followers[@]}" echo echo "Leader remote information:" git remote show -n "$leader" echo echo "Follower remotes information:" git remote show -n "${followers[@]}" echo branches=( $(git show-ref | sed -n 's| refs/remotes/'"$leader"'/|\t|p') ) echo -e "${#branches[*]} branches at leader:" echo "${branches[*]}" IFS=$'\t' errors=( ) error() { echo "XXX $1" >&2 errors[${#errors[*]}]="$1" } for branchspec in "${branches[@]}"; do set $branchspec leader_sha="$1" branch="$2" for remote in "${followers[@]}"; do echo echo "Updating $remote/$branch" # Prepare state to push follower_ref="refs/remotes/$remote/$branch" if ! git show-ref --verify --quiet "$follower_ref"; then echo "Branch doesn't exist yet at remote, creating" git reset --hard "$leader_sha" -- else echo "Branch existed at remote, updating" git reset --hard "$follower_ref" -- git merge --ff-only "$leader_sha" || { error "$remote $branch: FF not possible"; continue; } fi git push "$remote" "+HEAD:$branch" || { error "$remote $branch: failed to push"; continue; } done done if [[ "${#errors[*]}" -ge 0 ]]; then echo "Errors:" echo "${errors[@]}" else echo "No errors." fi