Created
June 23, 2021 07:08
-
-
Save lamchau/77b7cc9d9f5308ea9f47fa1c299ca24c to your computer and use it in GitHub Desktop.
Prune remote stale and merged branches that are >= 1 year old
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# used to execute branch deletes in parallel, shows progress bar | |
if ! [ -x "$(command -v parallel)" ]; then | |
echo "ERROR: Missing command 'parallel'" | |
exit 1 | |
fi | |
if ! [ -x "$(command -v git)" ]; then | |
echo "ERROR: Missing command 'git'" | |
exit 1 | |
fi | |
repo_url="$1" | |
if [ -z "$repo_url" ] || [ "$repo_url" == "-h" ] || [ "$repo_url" == "--help" ]; then | |
cat << __EOF__ | |
Usage: $(basename "$0") repo_url | |
Clones a bare git repository in order to fetch all remote branches. Then | |
deletes anything >= 1 year (relative time). Can be modified for absolute dates | |
swapping out \`\$format_relative\` -> \`\$format_absolute\`, and updating the | |
\`grep -v\` pattern. | |
To finalize, you must run git push --mirror to delete the branches upstream. | |
__EOF__ | |
exit 1 | |
fi | |
repo_name="$(basename "$repo_url")" | |
target_dir="${repo_name}-mirror" | |
if [ ! -d "$target_dir" ]; then | |
# clone a bare directory with all remote branches, which allows for | |
# a "dry run" committing to deletes (e.g. git push --mirror) | |
git clone "$repo_url" "$target_dir" --mirror | |
fi | |
if [ ! -d "$target_dir" ]; then | |
echo "Failed to clone: $repo_url" | |
exit 1 | |
fi | |
pushd "$target_dir" > /dev/null || exit 1 | |
# merged branches | |
git branch --merged | | |
cut -c3- | | |
grep --invert-match --extended-regexp 'master|deployable|HEAD' | | |
parallel --jobs 16 --bar git branch --delete --force {} | |
# shellcheck disable=SC2034 | |
format_absolute='%(committerdate:format:%Y-%m-%d)|%(refname:short)' | |
# stale branches (edge case for 12 months != 1 year) | |
format_relative='%(committerdate:relative)|%(refname:short)' | |
git for-each-ref --format="$format_relative" --sort=committerdate refs/heads | | |
awk 'BEGIN { FS = "|" }; { printf "%-25s%s\n", $1, $2 }' | | |
grep --extended-regexp "(\d+) year" | | |
cut -c26- | | |
parallel --jobs 16 --bar git branch --delete --force {} | |
cat << __EOF__ | |
To complete purging of stale branches, run | |
cd $target_dir | |
git push --mirror | |
Note: Errors may occur due if the target repository if Github but these can safely | |
be ignored | |
Excerpt from https://github.com/rtyley/bfg-repo-cleaner/issues/36#issuecomment-37877829: | |
The refs beginning 'refs/pull' are synthetic read-only refs created by | |
GitHub - you can't update (and therefore 'clean') them, because they | |
reflect branches that may well actually come from other repositories - ones | |
that submitted pull-requests to you. | |
So, while you've pushed all your real refs, the pull requests don't get | |
updated. There's no real way to fix them with your existing repo with the | |
GitHub admin tools. The severity of an issue depends on whether you were | |
trying to remove any 'private' data: | |
- Private data: the pull requests still have that private data in their | |
history - they will remain as a way for other people to retrieve that | |
data. The only ways to recover from this are to a) delete the repo using | |
the GitHub admin tools, and then recreate it, or b) contact GitHub | |
support and ask them to delete the PRs for you (they're pretty good about | |
it) | |
- Nothing Private: the pull requests still reference your old history - if | |
any of them are still open, you don't want to merge them into your new | |
fresh history! Get the submitters to rebase them on your new fresh | |
history before merging. | |
__EOF__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment