72

Stash enables automatic fork syncing if selected: https://confluence.atlassian.com/display/STASH/Keeping+forks+synchronized
It will update any branches in your fork that you haven't modified.

I've been unable to find similar automatic functionality in GitHub; all google searches are turning up manual ways to sync forks via your local cache.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Malina Kirn
  • 2,073
  • 1
  • 21
  • 19
  • 3
    Off the top of my head I don't think GitHub has this sort of feature, I think you need to sync manually. –  May 21 '14 at 20:34
  • 2
    This is a great question, long time annoyance of mine – Zombo May 22 '14 at 01:19
  • 3
    GitHub has really nice APIs, including webhooks and merging. While I don't think you can do this with GitHub alone, I'm sure you could make (or find) a bot that can automatically merge changes into a fork when there are no conflicts. – Nick McCurdy Dec 28 '14 at 05:49
  • http://stackoverflow.com/a/38802129/4696809 – Keval Bhatt Aug 06 '16 at 08:24
  • Related to: https://stackoverflow.com/questions/23793062/can-forks-be-synced-automatically-in-github – Evandro Coan Jul 29 '17 at 06:00
  • Possible duplicate of [How to automatically align/sync a forked Github origin/master branch to upstream/master?](https://stackoverflow.com/questions/28639713/how-to-automatically-align-sync-a-forked-github-origin-master-branch-to-upstream) – Evandro Coan Aug 04 '17 at 01:21
  • Good call: GitHub actions are a better answer than my 4 years old webhook answer. – VonC May 04 '20 at 15:14

4 Answers4

53

For the record, recently I ran into this same problem and addressed it with Github Actions. The solution is rather easy: an scheduled action fetches the upstream repository and merges it into mine.

# .github/workflows/example.yml

name: Merge upstream branches
on:
  schedule:
     # actually, ~5 minutes is the highest
     # effective frequency you will get
    - cron:  '* * * * *'
jobs:
  merge:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Merge upstream
        run: |
          git config --global user.name 'your-name'
          git config --global user.email 'your-username@users.noreply.github.com'

          # "git checkout master" is unnecessary, already here by default
          git pull --unshallow  # this option is very important, you would get
                                # complains about unrelated histories without it.
                                # (but actions/checkout@v2 can also be instructed
                                # to fetch all git depth right from the start)

          git remote add upstream https://github.com/example/test.git
          git fetch upstream

          # Neither forget the -b opt,
          # the feature/x ref is ambiguous at this stage
          git checkout -b feature/x origin/feature/x
          git merge --no-edit upstream/feature/x
          git push origin feature/x

          git checkout master
          git merge --no-edit upstream/master
          git push origin master

          # etc

I run it every Sunday which is more than enough for me. Just schedule this to whatever is fine for you.

Also, it is probably wiser to sync every branch in a different job since they will run in parallel and can independently succeed or fail if conflicts occur.

If you need to merge an arbitrary number of branches, you can refer to questions like How to fetch all Git branches to find shell tricks to do it.

I noticed a public action exists to address this by rebasing. It looked promising but it was fairly undocumented so here is my snippet instead. Hope it helps!

N1ngu
  • 2,862
  • 17
  • 35
48

You could define a webhook to listen to upstream (the original repo) changes, and update your fork.

In June 2016, you had the service backstroke.us which listens to those events for you. No need to write your own listener.
See 1egoman/backstroke

But, as commented by chriszo111, in 2020, that would be wei/pull

a GitHub App built with probot that keeps your forks up-to-date with upstream via automated pull requests.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 7
    Backstroke has ended, the creator links to similar approaches like https://github.com/wei/pull that seem to be maintained actively, also mentioned in https://stackoverflow.com/a/54718489/3423823 – chriszo111 Mar 17 '20 at 11:37
  • 1
    If you like the webhook approach, you might also want to take a look at https://n8n.io/. it's open-source, can be self-hosted but also provides a cloud offering. it's much cheaper than Zappier and other similar paid vendors. – Vadorequest Jan 04 '21 at 18:07
  • 3
    @Vadorequest Interesting. Of course, in 2020/2021, you now have the GitHub Action approach, like https://github.com/marketplace/actions/fork-sync – VonC Jan 04 '21 at 18:10
  • Yeah, I'd probably use a GitHub action for this too, looks like less work, and completely free for open source. – Vadorequest Jan 04 '21 at 18:12
27

You can create a Github App that use Github API to check the upstream repo periodically. Once an update is found, use Github API to create a pull request then call updateRef to update your branch to match master.

Or, just install this Github App that does exactly that

https://github.com/wei/pull

a GitHub App that keeps your repository up-to-date with upstream changes.

ddhhz
  • 381
  • 4
  • 6
  • This is a comment rather than an answer, as it is merely recommending a tool that already coded this, rather than answering the question of how to do it. – RaminS Feb 16 '19 at 00:13
  • 8
    @Gendarme The original poster says "all google searches are turning up manual ways to sync forks", and is asking for an automated way to do it. I've updated the answer a little bit to make it more clear. – ddhhz Feb 16 '19 at 00:19
2

I have a sync-fork Gist with a GitHub Action that keeps the repo up-to-date using the GitHub CLI. This is what it looks like right now (for completeness):

name: sync-fork
on:
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch: { }
jobs:
  sync:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - run: gh repo sync $REPOSITORY -b $BRANCH_NAME
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPOSITORY: ${{ github.repository }}
          BRANCH_NAME: ${{ github.ref_name }}
DearVolt
  • 358
  • 3
  • 13