#!/usr/bin/env bash # Adapted from SHOW_UPDATE=0 usage() { echo "usage: git ffwd [remote]..." echo "" echo "Fast forward all local branches tracking remote branches" echo "If given a list of remote, will update branches tracking those" echo "Otherwise will update all remotes" } ffwd() { CLB="$(git rev-parse --abbrev-ref HEAD)" for REMOTE in "$@"; do git remote update "$REMOTE" while read -r RB LB; do ARB="refs/remotes/$REMOTE/$RB" ALB="refs/heads/$LB" NBEHIND=$(( $(git rev-list --count "$ALB..$ARB" 2>/dev/null) +0)) NAHEAD=$(( $(git rev-list --count "$ARB..$ALB" 2>/dev/null) +0)) if [ "$NBEHIND" -gt 0 ]; then if [ "$NAHEAD" -gt 0 ]; then echo " branch $LB is $NBEHIND commit(s) behind and $NAHEAD commit(s) ahead of $REMOTE/$RB. could not be fast-forwarded" elif [ "$LB" = "$CLB" ]; then echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. fast-forward merge" git merge --ff -q "$ARB" # Can't reset the current branch else echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. resetting local branch to remote" git branch -f "$LB" -t "$ARB" >/dev/null fi elif [ "$SHOW_UPDATE" -eq 1 ]; then echo " nothing to do for branch $LB" fi done <<< "$(git remote show "$REMOTE" -n | awk '/merges with remote/{print $5" "$1}')" done } REMOTES=() if [ $# -gt 0 ]; then # Check for help flag for arg in "$@"; do case "$arg" in --help|-h) usage exit 0 ;; --show-update|-s) SHOW_UPDATE=1 ;; *) REMOTES+=("$arg") ;; esac done fi if [ ${#REMOTE[@]} -gt 0 ]; then # Call ffwd with all given remotes ffwd "${REMOTE[@]}" else # Call ffwd with all remotes in the repository ffwd "$(git remote)" fi