Skip to content

Instantly share code, notes, and snippets.

@IgnacioHeredia
Created August 9, 2022 07:45
Show Gist options
  • Save IgnacioHeredia/49f25805d2f2fbcf5bc0cec2afb0e925 to your computer and use it in GitHub Desktop.
Save IgnacioHeredia/49f25805d2f2fbcf5bc0cec2afb0e925 to your computer and use it in GitHub Desktop.
Github Action to keep fork updated with upstream
# Script is (loosely) based on two references:
# * https://stackoverflow.com/questions/23793062/can-forks-be-synced-automatically-in-github
# * https://stackoverflow.com/questions/69918635/how-to-keep-all-branches-and-tags-in-sync-in-a-fork-or-mirror-repo
# [!] Note: Do not do a force push to not overwrite the .github/workflow/main.yml file.
# We are not using a predefined action (eg. [1]) to not go through the hassle of having to
# manage Github Personal Access Tokens for deephdc.
# [1]: https://github.com/repo-sync/github-sync
name: Sync fork with upstream
on:
schedule:
# run at max frequency
- cron: '* * * * *'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Sync fork with upstream
run: |
#########################################################
# YOU SHOULD UPDATE THIS LINE
#########################################################
UPSTREAM_REPO=https://github.com/<username>/<reponame>.git
#########################################################
# Bot config
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
# Add remote
git remote add upstream $UPSTREAM_REPO
git fetch upstream
# Keep track of branch names
origin_branches=$(git branch -r | grep -v 'HEAD' | grep 'origin/' | cut -f 2 -d '/')
upstream_branches=$(git branch -r | grep 'upstream/' | cut -f 2 -d '/')
old_branches=$(comm -13 <(printf '%s\n' "${upstream_branches[@]}" | LC_ALL=C sort) <(printf '%s\n' "${origin_branches[@]}" | LC_ALL=C sort))
new_branches=$(comm -13 <(printf '%s\n' "${origin_branches[@]}" | LC_ALL=C sort) <(printf '%s\n' "${upstream_branches[@]}" | LC_ALL=C sort))
existing_branches=$(comm -13 <(printf '%s\n' "${new_branches[@]}" | LC_ALL=C sort) <(printf '%s\n' "${upstream_branches[@]}" | LC_ALL=C sort))
# Delete old branches from origin
echo "# Deleting old branches ..."
for tmp_branch in $old_branches; do
echo "## Processing $tmp_branch ..."
git push origin --delete $tmp_branch
done
# Create origin branches for new upstream branches
echo "# Creating new branches ..."
for tmp_branch in $new_branches; do
echo "## Processing $tmp_branch ..."
git checkout -b $tmp_branch upstream/$tmp_branch
git push origin
done
# Merge changes from upstream to origin for existing branches
echo "# Merging existing branches ..."
git config --add checkout.defaultRemote origin
for tmp_branch in $existing_branches; do
echo "## Processing $tmp_branch ..."
git checkout $tmp_branch
git merge --no-edit upstream/$tmp_branch
git push origin
done
# Sync tags
git tag -d $(git tag -l)
git fetch upstream --tags --quiet
git push origin --tags --force
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment