
Git Origin vs Upstream: Understanding Remote Repositories in Forking Workflows
When contributing to open-source software on GitHub or working within enterprise teams that utilize the Forking Workflow, managing multiple remote references in Git is a standard requirement. During setup, you will run commands referencing two remote targets: origin and upstream.
These names are not built-in Git keywords. They are alias conventions that represent your personal copy and the central repository.
In this guide, we will analyze what origin and upstream represent, map their roles in the developer loop, and step through the process of syncing your local code with the official repository.
Defining the Remotes
To understand the difference, imagine you want to contribute to an open-source project hosted at github.com/original-author/project-x.
Since you do not have write permissions to push code directly to the author's repository, you click the "Fork" button on GitHub. This creates a duplicate copy of the repository under your own account: github.com/your-username/project-x.
Next, you clone your fork to your local computer:
git clone https://github.com/your-username/project-x.gitThis setup defines the two remotes:
origin(Your Fork): Refers to your personal clone on GitHub. You have read/write access to this repository. This is where you push your custom feature branches to create Pull Requests.upstream(The Parent Repo): Refers to the original project repository on GitHub. You typically have read-only access. You fetch code from here to keep your local environment synchronized with changes made by other maintainers.
How to Configure the Upstream Remote
When you clone your fork, Git automatically configures a remote alias named origin pointing to your fork. However, it does not set up upstream automatically. You must add it manually.
Step 1: Add the Upstream Remote
Use git remote add to link your local workspace to the original parent repository:
git remote add upstream https://github.com/original-author/project-x.gitStep 2: Verify Your Remotes Configuration
List the active remote connections associated with your local repository:
git remote -vYour terminal should display four links:
origin https://github.com/your-username/project-x.git (fetch)
origin https://github.com/your-username/project-x.git (push)
upstream https://github.com/original-author/project-x.git (fetch)
upstream https://github.com/original-author/project-x.git (push)How to Sync Changes from Upstream to Origin
As other developers merge code into the parent repository, your fork (origin) falls behind. To bring the latest changes into your local workspace and push them to your fork, execute the following commands:
Step 1: Fetch Upstream Branch Commits
Download all branches and their respective commits from the original repository:
git fetch upstreamStep 2: Merge the Upstream Main Branch
Switch to your local main branch and merge the fetched commits from upstream/main into your local branch:
git checkout main
git merge upstream/main- Note: If you have uncommitted changes, stash them using
git stashbefore executing the merge.
Step 3: Push Updates to Your Origin Fork
Now that your local machine is updated, push the changes back to your GitHub fork:
git push origin mainYour fork on GitHub is now completely synchronized with the official upstream repository.
Remotes Comparison Summary
| Metric | origin | upstream |
| Whose Repo is it? | Your personal clone (Forked copy) | The original main repository |
| Write Permissions? | Read/Write (Direct pushes allowed) | Read-only (Requires Pull Requests) |
| Created When? | Configured automatically during clone | Added manually using git remote add |
| Primary Purpose | Publishing feature branches | Tracking official code updates |
Conclusion
Understanding Git remotes prevents repository alignment issues. By recognizing that origin points to your personal fork where you possess full write access, and upstream references the central authority where you fetch updates, you can configure clean syncing pipelines and contribute to team projects without git history conflicts.