By admin , 29 April 2026

What you will achieve

You will keep a fork of an open-source repository up to date with its upstream, sync your branches cleanly, and avoid the common pitfall of letting your fork drift weeks behind.

Step 1: confirm the remote setup

git remote -v

You want two remotes: origin for your fork and upstream for the source.

# If upstream is missing
git remote add upstream [email protected]:original-owner/project.git
git remote -v

Step 2: fetch upstream

git fetch upstream

This downloads new commits, branches, and tags from upstream without changing your working tree.

Step 3: update local main

git checkout main
git merge upstream/main --ff-only

--ff-only guarantees no merge commit; if local main has diverged (you committed to main directly), the merge fails. That is a feature - it tells you something needs untangling.

Step 4: push to your fork

git push origin main

Your fork's main now matches upstream's.

Step 5: rebase feature branches

For each active feature branch:

git checkout feature/login
git rebase main
# resolve conflicts if any
git push --force-with-lease

Step 6: configure pull behaviour

git config pull.rebase true
git config pull.ff only

Now git pull rebases by default and refuses non-fast-forward merges - your fork stays clean automatically.

Optional: GitHub's "Sync fork" button

The GitHub UI offers a "Sync fork" button on your fork's main page. It performs the equivalent of the above without the CLI. Useful for quick syncs; less flexible than the local workflow.

Optional: gh repo sync

gh repo sync yourname/project --branch main

The GitHub CLI command runs the sync server-side. Combine with a periodic GitHub Action for fully automated forks:

# .github/workflows/sync.yml
name: Sync upstream
on:
  schedule:
    - cron: '0 6 * * 1'   # weekly
  workflow_dispatch:
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: tgymnich/[email protected]
        with:
          owner: original-owner
          base: main
          head: main

Optional: pulling tags

git fetch upstream --tags
git push origin --tags

Useful if you depend on upstream tags (releases, version markers).

Common scenarios

Local main has diverged

git checkout main
git merge upstream/main --ff-only
# error: not possible to fast-forward, aborting

Reset local main to upstream's main (you lose any direct commits, which you should not have made):

git reset --hard upstream/main
git push --force-with-lease origin main

Upstream renamed default branch

Upstream changed master to main. Fix locally:

git fetch upstream
git branch -m master main
git branch --set-upstream-to=upstream/main main
git push origin :master main
# then update default branch on your fork via the GitHub UI

Forgot to keep in sync for months

git fetch upstream
git checkout main
git reset --hard upstream/main
git push --force-with-lease origin main

# rebase each feature branch
git checkout feature/whatever
git rebase main

Long divergence makes rebase conflict-prone. Sync weekly to keep conflicts small.

Best practice cadence

  • Daily for active contributors to busy projects.
  • Weekly for casual contributors.
  • Before each PR at minimum - reviewers expect your branch to start from current main.

The result

Your fork tracks upstream cleanly. Your feature branches start from current main. Reviewers do not bounce your PR with "please rebase". The work is mechanical and takes thirty seconds when done regularly.