Tutorial 5 of 8
Remotes: Clone, Fetch, Rebase, Push
Copy a project, catch up with your team's new commits, and share your own without making a mess.
About 6 minutes
What you will be able to do
- Clone a repository, and explain origin and remote-tracking branches such as origin/main.
- Use git fetch to download new commits without changing your own branch or files.
- Rebase your local commits onto the updated origin/main, then push them.
- Explain why you should never rebase commits you have already shared.
Title
Remotes. Clone, fetch, rebase, push.
This tutorial shows how your repository talks to a shared copy on a server.
What a remote is
A remote is another copy of the repository, usually on a server. When you clone, Git names it origin.
A remote is simply a named link to another copy of your repository, and origin is the usual name for the one you cloned from.
Analogy: a photocopied library
git clone copies the whole project, with all its history, and remembers where it came from.
git clone https://github.com/OWNER/notes-app.git cd notes-app git remote -v
A clone is a full, independent copy of the repository that records the source as a remote named origin.
Cloning is like photocopying an entire library, including its register of every past edition.
A photocopy never updates, and a clone does not update itself either, but a clone remembers its source as origin so you can fetch new commits any time.
origin/main is a bookmark
origin/main is your clone's memory of main on the server. It moves only when you fetch or push.
Remote-tracking branches like origin/main record what the server looked like the last time you talked to it.
Meanwhile, on the server
A teammate pushes C3 to the server. You commit L1 on your laptop. Neither of you sees the other's work yet.
Your laptop only knows what the server had at the last fetch, so C3 is still invisible to you.
Analogy: collecting mail without opening it
git fetch downloads new commits and moves origin/main. Your main and your files stay as they are.
git fetch origin git status
Fetch is always safe, because it only downloads commits and updates remote-tracking branches like origin/main.
Fetching is like collecting your letters from the post box and putting them on the table without opening them.
Unopened letters sit in a separate pile, but fetched commits are already stored in your repository; they just are not part of your branch until you merge or rebase.
Analogy: re-stacking plates
git rebase origin/main lifts your commits off and re-stacks them on top of the new base.
Rebase replays your commits on top of the updated branch, creating new commits so your history becomes a straight line.
Rebasing is like lifting your plates off one stack and placing them, in the same order, on a new base plate.
Moved plates are the same plates, but rebased commits are brand-new commits with new IDs, and the old ones are left behind.
Fetch, then rebase
Fetch first, then rebase onto origin/main. Conflict? Fix the file, git add it, then continue.
git fetch origin git rebase origin/main # if a conflict stops the rebase: # fix the file, then # git add <file> # git rebase --continue (or git rebase --abort to cancel) git log --oneline --graph
After fetching, rebasing onto origin/main puts your commit after your teammate's, and --abort takes you back if things go wrong.
Push
git push sends your new commits to the server. If the server has commits you lack, push is rejected. Fetch first.
git push origin main # first push of a new branch: git push -u origin my-branch
Push only succeeds when it adds to the server's history, which is why you fetch and rebase before pushing.
The golden rule of rebase
Never rebase commits you have already pushed and shared. Teammates have built on the old IDs.
Rebase is safe for local commits that nobody else has, but rewriting shared history causes duplicates and lost work for your team.
Re-stacking your own plates, before anyone else uses them, is harmless.
Once others hold copies of those commits, rewriting them leaves everyone with two versions of the same work, so rebase only your own unshared commits.
Recap
clone copies and remembers origin. fetch updates origin/main only. rebase re-stacks with new IDs. push shares your commits.
{"commits": [{"id": "C1", "parents": []}, {"id": "C2", "parents": ["C1"]}, {"id": "L1", "parents": ["C2"]}, {"id": "C3", "parents": ["C2"]}], "refs": [{"name": "main", "target": "L1", "kind": "branch"}, {"name": "origin/main", "target": "C3", "kind": "remote"}], "head": {"ref": "main"}}You can now work with a shared repository, and the last tutorial uses these steps to contribute to open source.
Check yourself
0 of 5 answered
Check 1 of 5
What does git fetch change in your repository?
Check 2 of 5
You run git rebase origin/main. Click the commit that becomes the parent of your new copy of L1.
C1 then C2. Your main has L1 on top of C2. origin/main is at C3, also on top of C2. HEAD is on main.
Check 3 of 5
Your push was rejected because the server has new commits. Put the needed commands in order. One card is not needed.
Tap the commands in the order you would run them. One is not needed.
Check 4 of 5
Why should you avoid rebasing commits that are already pushed to a shared branch?
Check 5 of 5
What does git clone set up for you?
mkdir -p ~/git-practice/t05-remotes && cd ~/git-practice/t05-remotes git init --bare -b main server.git # pretend this is the server # Teammate Asha starts the project and pushes it git init -b main asha cd asha git config user.name "Asha (practice)" # only for this practice repo echo "Welcome" > readme.txt && git add readme.txt && git commit -m "Add readme" git remote add origin ../server.git git push -u origin main cd .. # You clone the project git clone server.git you # Asha pushes another commit cd asha echo "Be kind" > rules.txt && git add rules.txt && git commit -m "Add rules" git push cd ../you # You commit without knowing about Asha's new commit echo "My idea" > idea.txt && git add idea.txt && git commit -m "Add idea" git push # rejected: fetch first git fetch git status # your branch and origin/main have diverged git log --oneline --graph --all git rebase origin/main git log --oneline --graph --all # a straight line now; note the new ID of "Add idea" git push