| |

GitHub 07 ๐ŸŒ Clones and Forks: Working with Remote Repositories

โฑ๏ธ Estimated read: 10 min | |

Cloning and forking are often confused because both create copies of a repository. But they operate in different places and serve different purposes. A clone is a local copy on your computer, created with git clone. A fork is a server-side copy on your GitHub account, created with the “Fork” button. The distinction matters because it determines how you contribute, how you synchronize, and whether your changes can be merged back into the original project.

Key point: A fork is a GitHub-level operation that creates a new repository under your account. A clone is a Git-level operation that downloads a repository to your machine. To contribute to a project you do not own, you fork it first, then clone your fork.


Why clones and forks exist

The access problem. You cannot push commits directly to a repository you do not own. GitHub’s permission model grants write access only to collaborators. If you find a bug in an open-source project and want to fix it, you need a repository you can push to. A fork provides thatโ€”it is a complete copy on your account with full write access, linked to the original (“upstream”) repository for pull requests .

The local work problem. Even if you own a repository, you cannot edit files directly on GitHub for any meaningful development. You need the code on your machine, with your editor, your build tools, and your test runner. git clone creates that local copy: the full commit history, all branches, and the working tree. Cloning is how you move from the browser to the terminal .

The contribution problem. A fork without a clone is a copy you cannot edit locally. A clone without a fork is a copy you cannot push to. The open-source workflow requires both: fork the upstream repository to your account, clone your fork to your machine, make changes, push to your fork, and open a pull request from your fork back to the upstream. Each step is necessary because of a specific constraint .

The synchronization problem. The upstream repository continues to change after you fork it. Your fork does not update automatically. If you want your fork to stay currentโ€”and you do, if you plan to submit a pull requestโ€”you must explicitly sync it. This can be done through the GitHub web interface, the GitHub CLI, or the command line with a configured upstream remote .

The trade-off. Forking creates a permanent link and a public association with the original project. Cloning is temporary and local. Forking a large repository duplicates its entire history on GitHub. Cloning copies it to your disk. The choice depends on whether you need to push changes back to a GitHub repository or only work locally.


a. Cloning a repository

git clone downloads a repository from GitHub to your local machine. The command creates a directory with the repository name, initializes a .git directory inside it, and sets up the origin remote pointing to the URL you cloned from.

# Clone via HTTPS
git clone https://github.com/OWNER/REPOSITORY.git

# Clone into a specific directory name
git clone https://github.com/OWNER/REPOSITORY.git my-project

# Clone only the latest commit (shallow clone)
git clone --depth 1 https://github.com/OWNER/REPOSITORY.git

After cloning, git remote -v shows origin pointing to the source URL. If you cloned your own repository, you can push directly to origin. If you cloned someone else’s repository, any git push will be rejected because you lack write access .

The clone includes every branch and the full commit history by default. This is why cloning a large repository can take time and disk space. The --depth flag creates a shallow clone with only the most recent commits, which is faster but limits git log and git blame to the available history.


b. Forking a repository

Forking is a GitHub operation. Clicking “Fork” on a repository page creates a new repository under your account with the same name, description, and code. The fork is independent: you can change its settings, add collaborators, and push commits without affecting the original .

# Fork via GitHub CLI
gh repo fork OWNER/REPOSITORY

# Fork and clone in one step
gh repo fork OWNER/REPOSITORY --clone

The fork retains a link to the original, displayed as “forked from OWNER/REPOSITORY” on the repository page. This link is what enables pull requests: you can open a PR from a branch on your fork to the corresponding branch on the upstream repository . The fork copies the code and commit history, but it does not copy issues, pull requests, or starsโ€”those remain with the upstream repository .

After forking, you still need to clone the fork to work locally. The clone URL is your fork’s URL, not the upstream URL. If you run git remote -v after cloning your fork, origin points to your fork. To track the upstream repository, you add a second remote.


c. Configuring upstream and syncing your fork

The upstream remote is a convention, not a requirement. It points to the original repository and allows you to fetch changes that were made after you forked. Without it, your fork diverges silently.

# Add the upstream remote (one time)
git remote add upstream https://github.com/ORIGINAL-OWNER/REPOSITORY.git

# Fetch changes from upstream
git fetch upstream

# Merge upstream changes into your local branch
git checkout main
git merge upstream/main

# Push the updated branch to your fork
git push origin main

The web interface offers a simpler method for syncing the default branch. On your fork’s page, a “Sync fork” button fetches the latest commits from upstream and updates your fork with a single click. If there are conflicts, GitHub prompts you to create a pull request to resolve them . The CLI equivalent is gh repo sync owner/fork -b branch, which updates the remote fork directly .

The git fetch upstream + git merge upstream/main + git push origin main sequence is the command-line version of the same operation. It gives you control over conflict resolution and allows syncing branches other than the default. The key detail is that merging upstream into your local branch does not update your GitHub forkโ€”the git push origin main step is required to transmit the merged state back to GitHub .


Complete Example Session

# ============================================
# PART 1: FORK THE UPSTREAM REPOSITORY
# ============================================

# On GitHub: navigate to OWNER/REPOSITORY
# Click "Fork" โ†’ "Create fork"
# The fork now exists at YOUR-USERNAME/REPOSITORY
# ============================================
# PART 2: CLONE YOUR FORK
# ============================================

git clone https://github.com/YOUR-USERNAME/REPOSITORY.git
cd REPOSITORY
# origin now points to your fork
# ============================================
# PART 3: ADD UPSTREAM REMOTE
# ============================================

git remote add upstream https://github.com/OWNER/REPOSITORY.git
git remote -v
# origin    https://github.com/YOUR-USERNAME/REPOSITORY.git (fetch)
# origin    https://github.com/YOUR-USERNAME/REPOSITORY.git (push)
# upstream  https://github.com/OWNER/REPOSITORY.git (fetch)
# upstream  https://github.com/OWNER/REPOSITORY.git (push)
# ============================================
# PART 4: CREATE A BRANCH FOR YOUR CHANGES
# ============================================

git checkout -b fix-typo
# Always work on a branch, never on main
# ============================================
# PART 5: MAKE CHANGES AND COMMIT
# ============================================

# Edit files...
git add .
git commit -m "Fix typo in README"
# ============================================
# PART 6: PUSH TO YOUR FORK
# ============================================

git push -u origin fix-typo
# The branch now exists on your fork
# ============================================
# PART 7: OPEN A PULL REQUEST
# ============================================

# On GitHub: navigate to OWNER/REPOSITORY
# GitHub detects your pushed branch and offers "Compare & pull request"
# Or: Pull requests โ†’ New pull request โ†’ compare across forks
# Base: OWNER/REPOSITORY main
# Head: YOUR-USERNAME/REPOSITORY fix-typo
# ============================================
# PART 8: SYNC YOUR FORK WITH UPSTREAM
# ============================================

git fetch upstream
git checkout main
git merge upstream/main
git push origin main
# ============================================
# PART 9: SYNC VIA WEB INTERFACE
# ============================================

# On your fork's page: "Sync fork" โ†’ "Update branch"
# Faster than CLI for the default branch

The nine parts trace the full workflow: forking, cloning the fork, adding upstream, creating a branch, committing, pushing, opening a pull request, syncing via CLI, and syncing via the web interface.


Quick Reference

Clone vs Fork

AspectCloneFork
LocationLocal machineGitHub account
Commandgit clone <url>“Fork” button or gh repo fork
PurposeWork on code locallyCreate a pushable copy
PushingTo origin (needs access)To your own repository
ContributionCannot open PR from clone aloneEnables pull requests

Remote Names

NamePoints toPurpose
originYour fork or the source you clonedPush changes here
upstreamThe original repositoryFetch changes from here

Sync Methods

MethodCommand
Web interface“Sync fork” button
CLIgh repo sync owner/fork -b main
Command linegit fetch upstream && git merge upstream/main && git push origin main

Best Practices

โœ… Do This:

git remote add upstream https://github.com/OWNER/REPOSITORY.git
  • โœ… Add upstream after cloning your fork
git checkout -b feature-branch
  • โœ… Work on a branch, never directly on main
git fetch upstream && git merge upstream/main
  • โœ… Sync before starting new work

โŒ Don’t Do This:

git clone https://github.com/OWNER/REPOSITORY.git
# Then try to push
  • โŒ You lack write access to the original
# Work on main and push to fork
  • โŒ Makes pull requests harder to manage
# Ignore upstream changes
  • โŒ Your fork diverges and conflicts accumulate

Common Pitfalls

PitfallWhy It HappensFix
Push rejected after cloning upstreamNo write accessFork first, then clone your fork
Fork not syncedNo upstream remote configuredgit remote add upstream <url>
Pull request has conflictsBranch based on stale mainSync main, rebase feature branch
origin points to upstreamCloned the original, not the forkgit remote set-url origin <your-fork-url>
Fork deleted when upstream is privateGitHub ownership rulesFork is deleted with private upstream

Real-World Examples

1. Clone Your Own Repository

git clone https://github.com/YOUR-USERNAME/my-project.git

2. Clone and Fork in One Step

gh repo fork OWNER/REPO --clone

3. Add Upstream Remote

git remote add upstream https://github.com/OWNER/REPO.git

4. Fetch Upstream Changes

git fetch upstream

5. Merge Upstream into Main

git checkout main && git merge upstream/main

6. Push Synced Main to Fork

git push origin main

7. Create Feature Branch

git checkout -b fix-typo

8. Push Feature Branch

git push -u origin fix-typo

9. Sync via Web

Fork page โ†’ "Sync fork" โ†’ "Update branch"

10. Shallow Clone

git clone --depth 1 https://github.com/OWNER/REPO.git

Visual

Clone vs Fork

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  UPSTREAM REPOSITORY (OWNER/REPO)            โ”‚
โ”‚  on GitHub                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ FORK (GitHub button)
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  YOUR FORK (YOUR-USERNAME/REPO)              โ”‚
โ”‚  on GitHub                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ CLONE (git clone)
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  LOCAL REPOSITORY                            โ”‚
โ”‚  on your machine                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Fork first, clone second. The fork is the pushable copy; the clone is the working copy.

Remote Configuration After Fork + Clone

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  LOCAL REPOSITORY                            โ”‚
โ”‚                                              โ”‚
โ”‚  origin    โ†’ YOUR-USERNAME/REPO              โ”‚
โ”‚              (push here)                     โ”‚
โ”‚                                              โ”‚
โ”‚  upstream  โ†’ OWNER/REPO                      โ”‚
โ”‚              (fetch from here)               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

origin is where you push. upstream is where you fetch.


Summary

ItemValue
Clone commandgit clone <url>
Fork commandGitHub “Fork” button or gh repo fork
Fork locationYour GitHub account
Clone locationYour local machine
Upstream remotePoints to the original repository
Sync CLIgit fetch upstream && git merge upstream/main
Sync web“Sync fork” button
Contribution pathFork โ†’ Clone โ†’ Branch โ†’ Push โ†’ Pull Request

Key takeaways:

  • A fork is a GitHub repository under your account. It is linked to the upstream repository and is the only way to push changes to a project you do not own .
  • A clone is a local copy. It downloads the repository to your machine for editing, building, and testing.
  • The contribution workflow requires both. Fork the upstream, clone your fork, make changes, push to your fork, and open a pull request from your fork to the upstream .
  • origin and upstream are conventions. After cloning your fork, origin points to your fork. Adding upstream allows you to fetch changes from the original repository .
  • Forks do not update automatically. You must sync your fork with upstream before starting new work, either through the web interface or the command line.
  • Work on branches, not main. A pull request should come from a feature branch, not from your fork’s main branch, so that main stays clean and syncable .

Remember: Cloning is how you get code onto your machine. Forking is how you get permission to push it back to GitHub. The open-source workflow is a sequence: fork the upstream, clone your fork, add the upstream remote, create a branch, commit, push to your fork, and open a pull request. Each step exists because of a constraint that would otherwise block the next one.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!