2025-02-20
6 min read

How to Update or Sync a Forked Repository on GitHub

How to Update or Sync a Forked Repository on GitHub

When you fork a repository on GitHub, you create your own copy of the project. Over time, the original repository (called the upstream) gets new commits that your fork does not have. To stay current, you need to sync your fork with the upstream repository.

TLDR: To sync a forked repository, add the original repository as an upstream remote with git remote add upstream <original-repo-url>, fetch the updates with git fetch upstream, and merge them into your branch with git merge upstream/main. Then push the changes to your fork with git push origin main.

In this guide, you'll learn how to keep your forked repository synchronized with the original project.

Prerequisites

You'll need a GitHub account with a forked repository, Git installed locally, and the fork cloned to your machine. Basic familiarity with Git commands and GitHub workflows will be helpful.

Understanding Forks and Upstreams

When you fork a repository, GitHub creates a complete copy under your account. Your fork is independent - changes to the original repository do not automatically appear in your fork:

Original Repo (upstream)          Your Fork (origin)
github.com/author/project   -->   github.com/you/project
        |                                 |
        |                                 |
    (diverge over time)               (your changes)

To keep your fork updated, you need to pull changes from the upstream repository and push them to your fork. This requires adding the upstream repository as a remote in your local clone.

Adding the Upstream Remote

First, check your current remotes to see what is already configured:

# View your current remotes
git remote -v

Typically, you'll see only your fork:

origin  https://github.com/your-username/project.git (fetch)
origin  https://github.com/your-username/project.git (push)

Now add the original repository as the upstream remote:

# Add the upstream repository
git remote add upstream https://github.com/original-author/project.git

# Verify the upstream was added
git remote -v

You should now see both remotes:

origin    https://github.com/your-username/project.git (fetch)
origin    https://github.com/your-username/project.git (push)
upstream  https://github.com/original-author/project.git (fetch)
upstream  https://github.com/original-author/project.git (push)

You only need to add the upstream remote once. Git remembers this configuration for future syncs.

Fetching Updates from Upstream

Fetching downloads the latest commits from the upstream repository without modifying your local files:

# Fetch all branches from upstream
git fetch upstream

This command downloads all new commits, branches, and tags from the upstream repository. Your local files remain unchanged - Git just updates its knowledge of what exists in the upstream repository.

You can verify what branches are available:

# List all remote branches
git branch -r

You'll see branches from both remotes:

  origin/main
  origin/feature-branch
  upstream/main
  upstream/develop
  upstream/release-1.0

Merging Upstream Changes

Before merging, make sure you're on the branch you want to update (typically main or master):

# Switch to your main branch
git checkout main

# Merge the upstream main branch
git merge upstream/main

This merges the commits from upstream/main into your local main branch. If there are no conflicts, Git completes the merge automatically. Your local repository now has all the commits from the upstream repository.

If you have no local commits on main, Git performs a fast-forward merge, simply moving your branch pointer forward:

Before merge:
  A---B---C  upstream/main
  |
  D  your main (behind)

After merge:
  A---B---C  both branches

Handling Merge Conflicts

If you've made commits to your main branch that conflict with upstream changes, you'll need to resolve conflicts:

# Attempt to merge
git merge upstream/main

# Git will notify you of conflicts:
# Auto-merging src/app.js
# CONFLICT (content): Merge conflict in src/app.js
# Automatic merge failed; fix conflicts and then commit the result.

Open the conflicted files and look for conflict markers:

<<<<<<< HEAD
// Your changes
function authenticate(user) {
  return user.token !== undefined;
}
=======
// Upstream changes
function authenticate(user) {
  return user.token && user.token.length > 0;
}
>>>>>>> upstream/main

Edit the file to resolve the conflict, removing the markers and keeping the code you want:

// Resolved version
function authenticate(user) {
  return user.token && user.token.length > 0;
}

Then complete the merge:

# Stage the resolved files
git add src/app.js

# Complete the merge
git commit -m "Merge upstream changes and resolve conflicts"

Pushing Updates to Your Fork

After merging upstream changes locally, push them to your fork on GitHub:

# Push to your fork
git push origin main

Your fork is now synchronized with the upstream repository. The changes appear in your GitHub repository, and both your local copy and remote fork are up to date.

Syncing Other Branches

If the project uses multiple branches (like develop or release branches), you can sync those too:

# Switch to the develop branch
git checkout develop

# If you do not have it locally, create it from upstream
git checkout -b develop upstream/develop

# Fetch and merge upstream develop
git fetch upstream
git merge upstream/develop

# Push to your fork
git push origin develop

This keeps all relevant branches in your fork synchronized with the upstream repository.

Using Rebase Instead of Merge

If you prefer to keep a linear history without merge commits, use rebase:

# Fetch upstream changes
git fetch upstream

# Rebase your changes on top of upstream
git rebase upstream/main

Rebasing replays your commits on top of the upstream commits, creating a cleaner history. After rebasing, force push to your fork (only if you have not shared this branch):

# Force push after rebase
git push --force origin main

Warning: Only use force push on branches that you're the sole contributor to. Never force push to shared branches.

Checking Sync Status

Before syncing, you might want to see how far behind your fork is:

# Fetch without merging
git fetch upstream

# Compare your branch to upstream
git log HEAD..upstream/main --oneline

This shows commits that exist in upstream/main but not in your local branch. If there is no output, you're already up to date.

To see the actual changes:

# View the diff between your branch and upstream
git diff HEAD..upstream/main

Keeping Your Fork Clean

If you do not plan to make any changes to the main branch, you can reset it to exactly match upstream:

# Fetch upstream
git fetch upstream

# Reset main to match upstream exactly
git reset --hard upstream/main

# Force push to your fork
git push --force origin main

This discards any commits you made to main and makes it identical to upstream. Only do this if you're certain you do not need those commits.

Now you know how to keep your forked repository synchronized with the upstream project. Regular syncing helps you stay current with bug fixes, new features, and security updates from the original repository. For active projects, consider syncing weekly or before starting new work on your fork.

Published: 2025-02-20|Last updated: 2025-02-20T11:00:00Z

Found an issue?