12 minlesson

Fork and Upstream Workflow

Fork and Upstream Workflow

When contributing to projects you don't have write access to, you work through a fork. This lesson covers the complete fork workflow used in open source development.

What is a Fork?

A fork is your personal copy of someone else's repository on GitHub. You can:

  • Push changes freely to your fork
  • Experiment without affecting the original
  • Submit pull requests to the original project
1┌─────────────────────────────────┐
2│ Original Repository │
3│ (github.com/org/project) │
4│ "upstream" │
5└───────────────┬─────────────────┘
6 │ fork
7
8┌─────────────────────────────────┐
9│ Your Fork │
10│ (github.com/you/project) │
11│ "origin" │
12└───────────────┬─────────────────┘
13 │ clone
14
15┌─────────────────────────────────┐
16│ Local Repository │
17│ (your machine) │
18└─────────────────────────────────┘

Creating a Fork

On GitHub

  1. Go to the repository you want to contribute to
  2. Click the "Fork" button (top right)
  3. GitHub creates a copy under your account

With GitHub CLI

bash
1$ gh repo fork org/project
2✓ Created fork you/project
3? Would you like to clone the fork? Yes
4Cloning into 'project'...

This forks and clones in one step.

Setting Up Remotes

After forking and cloning, configure two remotes:

RemotePoints ToPurpose
originYour forkPush your changes
upstreamOriginal repoPull latest changes

Rename Origin (Optional)

Some prefer explicit naming:

bash
1$ git remote rename origin origin-self

Add Upstream

bash
1$ git remote add upstream git@github.com:org/project.git

Verify Remotes

bash
1$ git remote -v
2origin git@github.com:you/project.git (fetch)
3origin git@github.com:you/project.git (push)
4upstream git@github.com:org/project.git (fetch)
5upstream git@github.com:org/project.git (push)

Syncing Your Fork

The original project continues to evolve. Keep your fork updated:

Fetch Upstream Changes

bash
1$ git fetch upstream
2From github.com:org/project
3 * [new branch] main -> upstream/main
4 abc1234..def5678 develop -> upstream/develop

Update Your Main Branch

bash
1$ git checkout main
2$ git rebase upstream/main
3First, rewinding head to replay your work on top of it...
4Fast-forwarded main to upstream/main.

Push Updated Main to Your Fork

bash
1$ git push origin main

If your fork has diverged, you may need:

bash
1$ git push origin main --force-with-lease

Contributing via Fork

Standard Workflow

bash
1# 1. Sync with upstream
2$ git fetch upstream
3$ git checkout main
4$ git rebase upstream/main
5
6# 2. Create feature branch
7$ git checkout -b feature/my-contribution
8
9# 3. Make changes
10$ vim file.txt
11$ git add file.txt
12$ git commit -m "feat: add my contribution"
13
14# 4. Push to your fork
15$ git push -u origin feature/my-contribution
16
17# 5. Open PR to upstream
18$ gh pr create --repo org/project --base main --head you:feature/my-contribution

PR from Fork to Upstream

When creating a PR from a fork, specify:

  • --repo: The upstream repository
  • --base: Branch in upstream to merge into
  • --head: Your fork and branch (username:branch)
bash
1$ gh pr create \
2 --repo org/project \
3 --base main \
4 --head you:feature/my-contribution \
5 --title "Add my contribution" \
6 --body "Description of changes"

Keeping Feature Branch Updated

If upstream changes while you're working:

bash
1# Fetch latest
2$ git fetch upstream
3
4# Rebase your feature onto updated main
5$ git rebase upstream/main
6
7# Force push to update PR
8$ git push --force-with-lease origin feature/my-contribution

Fork Sync Commands Summary

TaskCommands
Sync fork maingit fetch upstream && git checkout main && git rebase upstream/main && git push origin main
Update feature branchgit fetch upstream && git rebase upstream/main && git push --force-with-lease
Create PR to upstreamgh pr create --repo org/project --base main --head you:branch

Common Fork Workflows

Workflow 1: Quick Fix

bash
1$ gh repo fork org/project --clone
2$ cd project
3$ git checkout -b fix/typo
4# ... make fix ...
5$ git add . && git commit -m "fix: typo in readme"
6$ git push -u origin fix/typo
7$ gh pr create --repo org/project --fill

Workflow 2: Long-Term Contribution

bash
1# Initial setup (once)
2$ gh repo fork org/project --clone
3$ cd project
4$ git remote add upstream git@github.com:org/project.git
5
6# Before each contribution
7$ git fetch upstream
8$ git checkout main
9$ git rebase upstream/main
10$ git push origin main
11
12# Create feature
13$ git checkout -b feature/new-thing
14# ... work ...
15$ git push -u origin feature/new-thing
16$ gh pr create --repo org/project

Key Takeaway

Fork workflow: fork → clone → add upstream → sync regularly → branch → commit → push to fork → PR to upstream. Keep your fork synchronized with upstream to minimize merge conflicts when contributing.