#!/usr/bin/env bash merge-git-remote() { local git_folders git_folders=$(ls-git-folder .) for git_folder in $git_folders; do git_folder="${git_folder#./}" if ! git config -f .gitmodules --get-regexp "merge\.$git_folder\." &>/dev/null; then continue fi echo "=== Processing submodule: $git_folder ===" # Add explicit remotes from [remotes] section while IFS= read -r line; do local key value remote_name key=$(echo "$line" | awk '{print $1}') value=$(echo "$line" | awk '{print $2}') remote_name="${key##remotes.$git_folder.}" echo " Adding remote '$remote_name' -> $value" git -C "$git_folder" remote add "$remote_name" "$value" 2>/dev/null || \ git -C "$git_folder" remote set-url "$remote_name" "$value" git -C "$git_folder" fetch -q "$remote_name" done < <(git config -f .gitmodules --get-regexp "remotes\.$git_folder\." 2>/dev/null) local pinned_commit pinned_commit=$(git config -f .gitmodules submodule."$git_folder".commit 2>/dev/null) if [[ -n "$pinned_commit" ]]; then git -C "$git_folder" checkout -q -B merged "$pinned_commit" else git -C "$git_folder" checkout -q -B merged HEAD fi # Fetch origin once upfront for any origin merge refs if git config -f .gitmodules --get-regexp "merge\.$git_folder\.origin" &>/dev/null; then git -C "$git_folder" fetch -q origin fi while IFS= read -r line; do local key merge_ref remote_name tmp_ref key=$(echo "$line" | awk '{print $1}') merge_ref=$(echo "$line" | awk '{print $2}') remote_name="${key##merge.$git_folder.}" echo " Merging $remote_name/$merge_ref" tmp_ref="refs/merge-tmp/${remote_name}-$(echo "$merge_ref" | tr '/' '-')" if ! git -C "$git_folder" fetch -q "$remote_name" "$merge_ref:$tmp_ref"; then echo " !! Could not fetch $merge_ref from $remote_name — skipping" continue fi if ! git -C "$git_folder" merge -q --no-edit "$tmp_ref"; then echo " !! Merge conflict in $git_folder ($remote_name/$merge_ref) — resolve manually" fi done < <(git config -f .gitmodules --get-regexp "merge\.$git_folder\.") done }