#!/bin/bash set -eu [ -n "${DEBUG:-}" ] && set -x sync() { local this_branch="${1:?}" local base_branch="" local upstream="" # detect base branch (when git-new was used) [ -n "$base_branch" ] || base_branch=$(git symbolic-ref --short refs/baseof/"$this_branch" 2>/dev/null || :) # recursive [ -n "$base_branch" ] && sync "$base_branch" && git switch "$this_branch" # detect trunk via origin/HEAD [ -n "$base_branch" ] || base_branch=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null || :) # fallback to base branch == current branch [ -n "$base_branch" ] || base_branch=$this_branch # resolve upstream if [[ "$base_branch" != "origin/"* ]]; then upstream=$(git rev-parse --abbrev-ref --symbolic-full-name "$base_branch"'@{u}') else upstream=origin fi echo "Syncing $this_branch with $base_branch from $upstream" [ -n "${base_branch:?}" ] || exit 1 [ -n "${upstream:?}" ] || exit 1 # fetch upstream git fetch ${upstream/\// } # check if base and upstream have diverged if ! git diff --quiet "$upstream" "$base_branch"; then git diff --stat "$upstream" "$base_branch" fi # rebase git rebase --interactive "$upstream" "$this_branch" } sync "$(git symbolic-ref --short HEAD)"