GitHub 07 ๐ Clones and Forks: Working with Remote Repositories
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
| Aspect | Clone | Fork |
|---|---|---|
| Location | Local machine | GitHub account |
| Command | git clone <url> | “Fork” button or gh repo fork |
| Purpose | Work on code locally | Create a pushable copy |
| Pushing | To origin (needs access) | To your own repository |
| Contribution | Cannot open PR from clone alone | Enables pull requests |
Remote Names
| Name | Points to | Purpose |
|---|---|---|
origin | Your fork or the source you cloned | Push changes here |
upstream | The original repository | Fetch changes from here |
Sync Methods
| Method | Command |
|---|---|
| Web interface | “Sync fork” button |
| CLI | gh repo sync owner/fork -b main |
| Command line | git 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
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Push rejected after cloning upstream | No write access | Fork first, then clone your fork |
| Fork not synced | No upstream remote configured | git remote add upstream <url> |
| Pull request has conflicts | Branch based on stale main | Sync main, rebase feature branch |
origin points to upstream | Cloned the original, not the fork | git remote set-url origin <your-fork-url> |
| Fork deleted when upstream is private | GitHub ownership rules | Fork 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
| Item | Value |
|---|---|
| Clone command | git clone <url> |
| Fork command | GitHub “Fork” button or gh repo fork |
| Fork location | Your GitHub account |
| Clone location | Your local machine |
| Upstream remote | Points to the original repository |
| Sync CLI | git fetch upstream && git merge upstream/main |
| Sync web | “Sync fork” button |
| Contribution path | Fork โ 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 .
originandupstreamare conventions. After cloning your fork,originpoints to your fork. Addingupstreamallows 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
mainbranch, so thatmainstays 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.
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!