Build the mental model
Four words get tangled together constantly: clone, fork, fetch, and pull. Each does something distinct, and mixing them up causes real confusion.
Clone copies an entire remote repository — history, branches, everything — down to your local computer, once, so you have something to work with. You already used it in the Git tutorial.
Fork is different in kind, not just degree: it happens entirely on GitHub's servers, copying someone else's repository into your own GitHub account, with no local computer involved at all. Forking is usually the first step in contributing to a project you do not have push access to — you fork it to get your own copy, then clone your fork locally to actually write code.
| Operation | Details |
|---|---|
| Clone | Copies to your local computer, once. Not an ongoing sync — it's the starting copy. |
| Fork | Copies to your own GitHub account (server-side). No merge involved; it's a new remote repository. |
| Fetch | Copies remote commits into your local origin/main tracking ref. Does not merge into your current branch. |
| Pull | Copies remote commits and immediately merges them into your current branch, in one step. |
Fetch downloads any new commits from the remote and stores them under a remote-tracking reference like origin/main — your current branch does not move, and your working files do not change at all.
Pull does the same download, then immediately merges those new commits into your current branch, in one step. This is exactly why pull sometimes produces a surprise: an automatic merge commit, or even a conflict, appears without you actively deciding to combine anything.
The safer habit
Fetch first, inspect what changed with something like git log origin/main, and only then merge — this is the safer habit once a repository has more than one contributor pushing to it.
- Clone
- Copy an entire remote repository — history, branches, and all — down to your local computer, one time.
- Fork
- Copy someone else's repository into your own GitHub account, entirely on GitHub's servers, with no local computer involved.
- Fetch
- Download new commits from a remote into a local tracking reference (like origin/main) without touching your current branch.
- Pull
- Fetch new commits from a remote and immediately merge them into your current branch, in one step.
CLONE VS FORK VS FETCH VS PULL
------------------------------
GITHUB.COM YOUR COMPUTER
----------- -------------
your-account/repo <--- fork --- other/repo
|
| clone (once, full copy, local)
v
local clone --- fetch --> updates origin/main only
local clone --- pull --> fetch + merge into your branch
Fork = account to account, on GitHub only.
Clone / Fetch / Pull = remote to local, on your machine.Connect it to a real scenario
The demo for this lesson uses two local clones of the same bare repository to stand in for you and a teammate, so everything is real and reproducible without needing an actual GitHub account.
One clone commits a file and pushes; the second clone, representing you, has not seen that change yet.
Fetch
git fetch origin downloads the new commit but leaves your local main branch untouched — git log main still shows the old history, while git log origin/main shows the new commit sitting there, downloaded but not yet merged.
Merge
git merge origin/main folds it in, fast-forwarding your branch since there was no conflicting local work.
Pull (the one-step version)
After a second teammate commit, git pull origin main performs the fetch and the merge together, and the fast-forward happens automatically without a separate merge command.
Compare the two approaches directly in your own terminal — notice that fetch alone never touched your working files, while pull changed them immediately. That difference is the entire lesson.
Try the working example
git init --bare remote-demo.git
git clone remote-demo.git clone-a
cd clone-a
echo "# Demo Project" > README.md
git add README.md
git commit -m "Initial commit"
git push origin main
cd ..
git clone remote-demo.git clone-b
cd clone-b
echo "Some notes" > notes.md
git add notes.md
git commit -m "Add notes from teammate"
git push origin main
cd ../clone-a
git log --oneline
git fetch origin
git log main --oneline
git log origin/main --oneline
git merge origin/main
git log --oneline
# after a second teammate commit + push:
git pull origin main
git log --onelinegit log --oneline (in clone-a, before fetch):
df3882e Initial commit
git fetch origin:
From .../remote-demo
df3882e..56447b2 main -> origin/main
git log main --oneline (unchanged after fetch):
df3882e Initial commit
git log origin/main --oneline (the new commit is here, not yet merged):
56447b2 Add notes from teammate
df3882e Initial commit
git merge origin/main:
Updating df3882e..56447b2
Fast-forward
notes.md | 1 +
1 file changed, 1 insertion(+)
git log --oneline (after merge):
56447b2 Add notes from teammate
df3882e Initial commit
(after a second teammate commit and push) git pull origin main:
From .../remote-demo
56447b2..9469944 main -> origin/main
Updating 56447b2..9469944
Fast-forward
notes.md | 1 +
1 file changed, 1 insertion(+)
git log --oneline (after pull):
9469944 Update notes with second point
56447b2 Add notes from teammate
df3882e Initial commit5-minute try-it
Set up two repositories (a bare remote plus two clones) yourself. Commit and push from one clone. In the other, run git fetch and observe the difference between git log main and git log origin/main firsthand, then merge.
One important caution
Running git pull without realizing it merges automatically, and being surprised by a merge commit or conflict
Cloning a project directly and trying to push without push access — forgetting you need to fork first, then clone your own fork
GitHub Docs: Getting changes from a remote repository — Git & GitHub