Skip to content

Instantly share code, notes, and snippets.

@summersab
Created September 12, 2023 16:26
Show Gist options
  • Save summersab/faf335c03d8d1686c258354e1d58a418 to your computer and use it in GitHub Desktop.
Save summersab/faf335c03d8d1686c258354e1d58a418 to your computer and use it in GitHub Desktop.
Simple script to keep the local and remote origin of forked repos fresh
#!/bin/bash
if [[ -z "${1}" ]] || [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]
then
echo "This is a simple script to keep the local and remote of your forked"
echo "repositories fresh. It does so by:"
echo " 1. Detecting if the repo's origin and upstream are different (indicating"
echo " a fork)"
echo " 2. Performing a \`fetch --all\` on the repo to update from origin and"
echo " upstream"
echo " 3. Pushing any changes to the repo's origin to keep it updated, as well"
echo ""
echo "Usage: git-update.sh <search-path> <ssh-certificate>"
echo ""
echo "Please specify a path for the script to use to find git repositories."
echo ""
echo "Optionally, specify the path of a SSH certificate if one is needed for"
echo "accessing/updating the repositories in the search path. This should also"
echo "be provided if your SSH cert is password protected so the script will"
echo "only request your password once."
echo ""
exit
fi
if [ ! -z "${2}" ]
then
eval $(ssh-agent) 1>/dev/null
ssh-add "${2}"
gitparams="'ssh -i ${2}'"
echo "${gitparams}"
fi
echo ""
echo "Searching for .git directories in "$(realpath ${1})
for repo in $(find "${1}" -name .git -type d)
do
dirname="${repo::-4}"
# This checks to see if the upstream and origin are different (indicating a fork)
if [[ $(git -C "${dirname}" remote get-url upstream 2>/dev/null) != "" ]] && \
[[ $(git -C "${dirname}" remote get-url origin) != $(git -C "${dirname}" remote get-url upstream 2>/dev/null) ]]
then
# Get the current and default (i.e. master/main) branch names
current=$(git -C "${dirname}" rev-parse --abbrev-ref HEAD)
default=$(git -C "${dirname}" symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')
echo "Updating $(basename $(git -C "${dirname}" rev-parse --show-toplevel 2>/dev/null) 2>/dev/null):${default} in ${dirname}"
# If the current and default branch names are different, the repo is
# currently on a branch other than the default. Stash any changes
if [[ "${current}" != "${default}" ]]
then
git -C "${dirname}" stash &>/dev/null
fi
# Switch to the master branch and `fetch --all`
git -C "${dirname}" switch ${default} &>/dev/null
git -C "${dirname}" fetch --all 2>&1 | sed "s/^/ /"
# Push any updates to the remote origin
if [ ! -z "${2}" ]
then
GIT_SSH_COMMAND="ssh -i ${2}" git -C "${dirname}" push origin "${current}" 2>&1 | sed "s/^/ /"
else
git -C "${dirname}" push origin "${current}" 2>&1 | sed "s/^/ /"
fi
# If necessary, switch back to the previous branch and restore the stash
git -C "${dirname}" switch ${current} &>/dev/null
if [[ "${current}" != "${default}" ]]
then
git -C "${dirname}" stash pop &>/dev/null
fi
echo ""
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment