Skip to content

Instantly share code, notes, and snippets.

@Daenyth
Last active November 8, 2023 15:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Daenyth/94eab3f29827dd1ae641246bdff4d2ef to your computer and use it in GitHub Desktop.
Save Daenyth/94eab3f29827dd1ae641246bdff4d2ef to your computer and use it in GitHub Desktop.
Git refresh
#!/usr/bin/env bash
set -o errexit
## git refresh
#
# Update all git remotes
# Update local main or master branch from the remote
# Delete local branches tracking remotely-deleted branches
# Delete local branches that have been merged
# Print local branches that are outdated
function checkbranch {
name="$1"
status="$(git branch -l "$name" --format '%(refname:short)')"
if [[ -z "$status" ]]; then
return 1
else
return 0
fi
}
if checkbranch main; then
MAINBRANCH=main
elif checkbranch master; then
MAINBRANCH=master
else
# If we have an "upstream" branch, then our git clone is probably a fork - we should use their default branch and not origin
if git remote | grep -q upstream; then
remote=upstream
else
remote=origin
fi
# Attempt to detect the branch github declares as the main one, if possible
remote_url=$(git remote get-url $remote)
if [[ $remote_url == git@github.com* ]]; then
# This git repo is tracking github
# Extract the username and repository name from the URL
username=$(echo $remote_url | cut -d: -f2 | cut -d/ -f1)
repository=$(echo $remote_url | cut -d/ -f2 | cut -d. -f1)
echo "main branch not detected - attempting to query from $username/$repository on github"
# Try to find github auth in case the repo is private
if [[ -n $GITHUB_TOKEN ]]; then
token="$GITHUB_TOKEN"
elif [[ -n $GH_TOKEN ]]; then
token="$GH_TOKEN"
fi
if [[ -n $token ]]; then
auth_args="-H \"Authorization: Bearer $token\""
else
auth_args=""
fi
# Ask github what the main branch is, using auth if we found it
MAINBRANCH=$(curl -s $auth_args https://api.github.com/repos/$username/$repository | jq -r .default_branch)
echo "Detected $MAINBRANCH as the default branch on github"
fi
fi
if [[ $1 == "-m" ]]; then
if [[ -n $2 ]]; then
MAINBRANCH="$2"
fi
if [[ -z $MAINBRANCH ]]; then
echo "Cannot change branch to main: main branch not detected. Run \`git refresh -m mainbranchname\` to change branches"
exit 1
fi
git checkout $MAINBRANCH
shift
elif [[ -n $1 ]]; then
MAINBRANCH="$1"
fi
git remote update --prune || true
if [[ -n $MAINBRANCH ]]; then
if [[ "$(git branch | sed -n '/\* /s///p')" == "$MAINBRANCH" ]]; then
# On master, fast forward.
git merge --ff-only origin/$MAINBRANCH
else
# force-set local master to point at origin/master's commit
# Do this to avoid changing the reflog, or invalidating compiler cache etc
git branch -f $MAINBRANCH origin/$MAINBRANCH
fi
# Delete local branches that have been merged to main
git branch --merged origin/$MAINBRANCH | grep -v $MAINBRANCH | grep -vF '*' | xargs git branch -d
else
echo "main branch not detected. Run \`git refresh branchname\` to treat \`branchname\` as a main branch"
fi
echo "Outdated"
# Delete local branches which are tracking a remote branch which is gone (eg squash+merge on github)
git branch --format '%(upstream:track,nobracket)%09%(refname:short)' | awk -F "\t" '{ if($1 = /gone/) { print $2 } }' | xargs git branch -D
# List local branches not merged to master
if [[ -n $MAINBRANCH ]]; then
git branch --no-contains origin/$MAINBRANCH --sort=-committerdate -vv
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment