βοΈ Lesson 5: GitHub: Push, Pull & Clone
So far, your whole history lives in one hidden .git folder on one computer. If that laptop dies, the history dies with it. In this lesson you'll give your site a second home on GitHub: you'll push your commits up, pull changes back down, and clone a full copy anywhere. This is also the setup you need for automatic deploys in the next lesson.
π― Learning Objectives
By the end of this lesson, you will be able to:
- Create a free GitHub account and an empty repository, and explain why it should be empty
- Connect your local repository to GitHub with
git remote add originand check it withgit remote -v - Push your commits with
git push -u origin main(the first time) andgit push(every time after) - Sign in to GitHub from Git the easy way: Git Credential Manager, VS Code, or the GitHub CLI
- Bring changes made on GitHub.com down with
git pull - Make a complete copy of any repository with
git clone - Write a short
README.mdin Markdown, and choose public or private visibility safely
Estimated Time: 50 minutes
Project: Put your my-website repository on GitHub, add a README, and practice the push β pull β clone round trip
In This Lesson
π Local and Remote
Remember this morning: Git is the tool on your computer, and GitHub is a website that hosts Git repositories. Everything you've done so far (commits, branches, the merge conflict) happened in your local repository. Nobody else can see it, and there's only one copy.
A remote is another copy of the same repository that lives somewhere else, here on GitHub. Git doesn't sync automatically like Dropbox. You decide when to send and receive, with two commands:
git pushsends your new commits up to GitHub.git pullbrings new commits down from GitHub and merges them into your branch.
Once your commits are on GitHub you get three big wins: a backup off your laptop, a way to work from any computer, and (next lesson) automatic deploys to Netlify every time you push.
π€ Your GitHub Account
If you don't have one yet, go to github.com/signup and create a free account. The free plan includes unlimited public and private repositories, which is everything you need today.
- Enter your email, a password, and a username. Your username appears in all your repository URLs (
github.com/your-username/my-website), so pick something you'd be happy to put on a rΓ©sumΓ©. - Verify your email address (GitHub sends a code or a link).
- GitHub may ask you to turn on two-factor authentication (2FA) with an authenticator app or a passkey. Do it when asked; it protects your code. Save the recovery codes somewhere safe.
π‘ Your commit email
In Lesson 1 you set user.email. GitHub links commits to your account when that email is one of the addresses on your account. If you'd rather keep your real address out of public history, GitHub gives you a private noreply address under Settings β Emails (it looks like 12345678+your-username@users.noreply.github.com). You can switch to it any time with git config --global user.email. It only affects future commits.
π¦ Create an Empty Repository
You already have a repository with history on your computer. On GitHub you'll create an empty one to receive it.
- On GitHub, click the + button at the top right and choose New repository.
- Owner: your username. Repository name:
my-website(it doesn't have to match your folder name, but matching keeps life simple). - Description (optional): something like "My first website, built in the HTML & CSS course".
- Visibility: Public or Private. Either works for today (more on this below).
- Leave every "initialize" option off: no README, No .gitignore, No license. Depending on GitHub's current layout these appear as switches or drop-downs; just make sure none of them adds a file.
- Click Create repository.
β οΈ Why it must be empty
If you tick "Add README", GitHub makes a first commit on its side. Now GitHub has a history that starts with its README commit, and your laptop has a history that starts with your first commit. The two histories have nothing in common, so your first push is rejected, and fixing it is fiddly for a beginner. Start empty, push, and add a README afterwards (you will, in a few minutes).
Because the repository is empty, GitHub shows a Quick setup page. Find the section titled "β¦or push an existing repository from the command line". Make sure HTTPS is selected (not SSH) and copy the URL. It looks like this:
https://github.com/your-username/my-website.git
GitHub also lists three commands there, including git branch -M main. That one renames your branch to main; yours already is main from Lesson 1's setup, so running it is harmless but unnecessary. Keep this page open.
π Connect: git remote
Open your my-website folder in VS Code and open the integrated terminal (Ctrl+`, on a Mac too). First, make sure everything is committed:
git status
You want to see nothing to commit, working tree clean on branch main. Now tell Git where the remote lives. Paste your URL, not the example:
git remote add origin https://github.com/your-username/my-website.git
That command prints nothing when it works. Let's break it down:
git remote add: "remember a remote repository for me"origin: the nickname for it.originis the standard name for "the main remote", so everyone uses it.- the URL: where it lives
Check it:
git remote -v
origin https://github.com/your-username/my-website.git (fetch)
origin https://github.com/your-username/my-website.git (push)
Two lines, same URL: one for receiving (fetch) and one for sending (push).
π‘ Typo in the URL?
If you pasted the wrong URL, don't add a second remote. Fix the existing one:
git remote set-url origin https://github.com/your-username/my-website.git
If you see error: remote origin already exists., that means you already added it. Check it with git remote -v and use set-url if it's wrong.
π Your First Push
git push -u origin main
In plain English: "push my main branch to origin, and remember that this branch goes with origin/main from now on." The -u (short for --set-upstream) is only needed once per branch. After that, a plain git push knows where to go.
The very first time, Git will ask you to sign in to GitHub. The next section shows what that looks like. Once you're signed in, you'll see something like this (the numbers will differ):
Enumerating objects: 18, done.
Counting objects: 100% (18/18), done.
...
Writing objects: 100% (18/18), 41.52 KiB | 5.19 MiB/s, done.
To https://github.com/your-username/my-website.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.
The two lines that matter: * [new branch] main -> main (your main now exists on GitHub) and set up to track 'origin/main' (that's what -u did). Now run:
git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
That new second line appears now that your branch has an upstream. Refresh the GitHub page in your browser. Your files are there, and if you click the commit count (the clock icon with "N Commits"), every commit from today is listed with its message. π
β Every push after this one
git push
That's it. If you ever forget the -u on a new branch, Git tells you exactly what to type:
fatal: The current branch main has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin main
--set-upstream is the long spelling of -u. Git error messages are often this helpful: read them slowly.
π Signing In from Git
GitHub needs to know the push really comes from you. One important fact first: your GitHub password does not work in the terminal. GitHub stopped accepting account passwords for Git operations in August 2021. If Git prints Username for 'https://github.com': and you type your username and password, you'll get Authentication failed (or a "Password authentication is not supported" message). That's not you doing it wrong. It's a sign you need one of the easy paths below.
Path 1: Git Credential Manager (Windows: already installed)
The Git for Windows installer from Lesson 1 included Git Credential Manager (GCM). On your first push, a small "Connect to GitHub" window pops up. Choose Sign in with your browser, approve the request in the browser tab that opens (it asks you to authorize Git Credential Manager), and go back to the terminal. The push finishes, and GCM stores the sign-in securely so you won't be asked again.
On a Mac, GCM isn't included with Apple's Git; use Path 2 or Path 3 instead. (If you like Homebrew, brew install --cask git-credential-manager adds it.)
Path 2: VS Code
VS Code has GitHub sign-in built in. If you push from the Source Control panel (the Sync Changes or Publish Branch button, or β¦ β Push), VS Code shows a prompt like "The extension 'GitHub' wants to sign in using GitHub". Click Allow, approve in the browser, and you're connected. VS Code then also answers Git's sign-in requests from its own integrated terminal. You may also see Publish to GitHub on a repository with no remote yet; that button creates the GitHub repository and pushes in one go. It's a fine shortcut, but do it by hand today so you understand each step.
Path 3: GitHub CLI (gh auth login)
The GitHub CLI is a free, official command-line tool from cli.github.com (Windows: installer or winget install --id GitHub.cli; Mac: brew install gh). After installing, close and reopen your terminal, then run:
gh auth login
It asks a few questions. Use the arrow keys and Enter:
- Where do you use GitHub? β GitHub.com
- What is your preferred protocol for Git operations on this host? β HTTPS
- Authenticate Git with your GitHub credentials? β Yes (this is the important one: it sets Git up to use this sign-in)
- How would you like to authenticate GitHub CLI? β Login with a web browser
It shows a one-time code like ABCD-1234. Press Enter, paste the code into the browser page, approve, and you'll see β Logged in as your-username. Now git push just works.
β οΈ Personal access tokens: fallback only
Older tutorials say to create a personal access token (PAT) and paste it where Git asks for a password. That still works, but it's a long secret string you must create, protect, and renew, so treat it as a last resort if the three paths above fail. Never paste a token into a file in your project, a chat, or a screenshot: anyone who has it can act as you.
π Add a README
GitHub shows a file named README.md right under your file list. It's the front door of your repository: what this is, and how to see it. The .md means Markdown, a simple way to format text with ordinary characters.
In VS Code, create a new file named README.md in the top of my-website (next to index.html) and write something like this:
# My Website
My first multi-page website, built in the HTML & CSS course.
## Pages
- **Home**: `index.html`
- **About**: `about.html`
- **Contact**: `contact.html`
## Built with
- HTML and CSS
- Version control with Git, hosted on GitHub
Live site: https://your-site-name.netlify.app
The Markdown you need today:
| You type | You get |
|---|---|
# Title | A big heading (like <h1>) |
## Section | A smaller heading (like <h2>) |
- item | A bulleted list item |
**bold** | bold |
`code` | code |
| a blank line | a new paragraph |
Tip: in VS Code, press Ctrl+Shift+V (Cmd+Shift+V on Mac) to preview Markdown. Now the same three steps as always, plus a push:
git add README.md
git commit -m "Add README describing the site"
git push
Refresh GitHub: your README now appears, nicely formatted, under the file list.
β¬οΈ Pull Changes Down
Sometimes the newest commit isn't on your laptop: you fixed a typo on GitHub.com from your phone, you pushed from another computer, or (later) a teammate pushed. git pull brings those commits down.
First, a one-time setting
Run this once. It tells Git: "if my laptop and GitHub both have new commits when I pull, combine them with a normal merge", just like the merges you did in Lesson 4.
git config --global pull.rebase false
Without it, newer versions of Git stop in that situation with fatal: Need to specify how to reconcile divergent branches. and a list of choices. (If you ever see that message, this is the setting it's asking for.)
Try it: edit on GitHub, pull to your laptop
- On GitHub, click
README.md, then the pencil icon (Edit this file). - Add a line, for example
Made with β and a lot of Git commits. - Click Commit changesβ¦. In the dialog, keep the message or improve it, leave Commit directly to the main branch selected, and click Commit changes.
GitHub now has one commit your laptop doesn't. Back in VS Code's terminal:
git status
On branch main
Your branch is up to date with 'origin/main'.
"Up to date"? That's not a bug. git status doesn't contact GitHub. It compares against the last thing Git heard from GitHub. To actually go and get the new commit:
git pull
From https://github.com/your-username/my-website
5e4edf3..368abf2 main -> origin/main
Updating 5e4edf3..368abf2
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
Recognize Fast-forward from Lesson 4? A pull is really two steps: fetch (download new commits) and merge (combine them into your branch). Open README.md in VS Code: your GitHub edit is there.
β οΈ "Updates were rejected"
If you commit on your laptop and someone (maybe you, on GitHub) committed first, your push is refused:
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/your-username/my-website.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. ...
Nothing is broken and nothing was lost. GitHub is saying "get my new commits first". Run git pull (VS Code may open a tab with a merge message; close it to finish), then git push again. If both sides changed the same line, you'll get a merge conflict, and you already know how to fix one from Lesson 4. Never "fix" a rejected push with --force; that throws away the other commits.
π‘ Habit: pull before you start
Start every work session with git pull. If there's nothing new, it just says Already up to date., and you've avoided a rejected push later.
π₯ Clone a Repository
git clone downloads a complete copy of a repository: every file, every commit, every message, with origin already set up. It's how you'd set up your site on a new laptop, or get a copy of someone else's public project.
Let's prove your GitHub copy is complete by cloning it into a different folder. In the terminal, go up one level out of my-website, so you don't create a repository inside a repository:
cd ..
git clone https://github.com/your-username/my-website.git my-website-copy
Cloning into 'my-website-copy'...
remote: Enumerating objects: 24, done.
...
Receiving objects: 100% (24/24), 43.10 KiB | 1.20 MiB/s, done.
The last word, my-website-copy, names the new folder. Leave it off and Git uses the repository name. Now look inside:
cd my-website-copy
git log --oneline
Every commit you made today is there. This is your backup working. When you're done looking, cd .. back out, then cd my-website to return to your real project. You can delete my-website-copy in your file explorer; the original is untouched.
π‘ Clone something that isn't yours
Any public repository can be cloned: a classmate's site (ask for their URL) or an open-source project. Click the green Code button on its GitHub page, copy the HTTPS URL, and git clone it into a new folder. You can look, run it with Live Server, and even commit locally. You just can't push to a repository you don't have permission for (that's what pull requests are for, next lesson).
π The Everyday Loop
Put it all together and your daily routine with GitHub is four steps:
git pull
# ...edit files in VS Code, check them in Live Server...
git add .
git commit -m "Describe what you changed and why"
git push
You can commit several times before pushing. Pushing sends all of them at once.
The same loop in VS Code
The Source Control panel shows your branch at the bottom-left of the window, with small arrows and numbers next to it (β commits to pull, β commits to push). After you commit, the big button changes to Sync Changes; clicking it pulls and then pushes. On a branch that isn't on GitHub yet, the button says Publish Branch. It's the same Git underneath, so use whichever you like. If VS Code asks whether to "periodically run git fetch", that's safe to allow: it just keeps the arrows up to date.
π Public, Private & Secrets
| Public | Private | |
|---|---|---|
| Who can see the code | Anyone on the internet | Only you and people you invite |
| Good for | Portfolios, learning projects, showing employers your work | Client work, drafts, anything you're not ready to share |
| Works with Netlify (next lesson) | Yes | Yes |
You can change it any time under the repository's Settings tab β General β Danger Zone β Change repository visibility. (A website's HTML and CSS are visible to any visitor anyway, so a public repository doesn't reveal much more.)
β Never push secrets
Passwords, API keys, access tokens, private notes, personal documents: keep them out of your repository, even a private one. Git remembers everything. Deleting a file in a later commit doesn't remove it from history, so anything pushed should be treated as leaked. If you ever push a real key by mistake, cancel or change that key with the service that issued it straight away; that's the actual fix. Use .gitignore (Lesson 2) for files that should never be committed, and run git status before every commit so you know exactly what's going in.
β Common Questions
Does GitHub update automatically when I save a file?
No. Saving changes your working folder. Committing saves a snapshot in your local repository. Only git push sends commits to GitHub. If GitHub looks out of date, check that you committed and pushed.
What's the difference between origin and main?
origin is the nickname for the place (your repository on GitHub). main is a branch. git push origin main means "send my main branch to origin". origin/main is your laptop's memory of where GitHub's main branch was last time you talked to it.
I made the repository with a README by accident. Now what?
The simplest fix on day one: delete that GitHub repository (Settings β General β Danger Zone β Delete this repository) and create it again, empty. Your local repository is untouched, so nothing is lost. (Point origin at the new URL with git remote set-url if the name changed.)
Do I need SSH keys?
Not for this class. HTTPS plus one of the sign-in paths above is all you need. SSH keys are another sign-in method many developers set up later; GitHub's documentation walks through it when you're ready (Connecting to GitHub with SSH).
ποΈ Hands-on Exercise
ποΈ Exercise: Your Site's Second Home
Objective: Get your my-website repository onto GitHub and complete one full round trip: push up, change on GitHub, pull down, clone a copy.
Instructions:
- Run
git statusinmy-website. Commit anything left over so the working tree is clean. - On GitHub, create an empty repository named
my-website(no README, no .gitignore, no license). Copy the HTTPS URL. - Connect it with
git remote add originand check withgit remote -v. - Push with
git push -u origin main, signing in when asked. Refresh GitHub and find your commit history. - Create
README.mdwith a heading, one sentence about your site, and a bulleted list of your pages. Commit it andgit push. - Run
git config --global pull.rebase falseonce. - On GitHub, edit
README.mdin the browser and commit the change. Then rungit pullon your laptop and confirm the change arrived. - From the folder above
my-website, clone your repository intomy-website-copyand rungit log --onelineinside it. Then go back tomy-website.
Deliverable: your repository URL, https://github.com/your-username/my-website, showing your site files, a formatted README, and today's commits. Keep it handy: you'll connect Netlify to it next lesson.
π‘ Hint
Stuck on the push? Read the last lines Git printed. remote origin already exists means step 3 already worked. src refspec main does not match any means you have no commits yet on main (or your branch has another name; git branch will tell you). Authentication failed means Git tried your password; use Git Credential Manager, VS Code, or gh auth login instead. rejected ... (fetch first) means GitHub has commits you don't: git pull, then push again.
β Solution
# 1. In my-website
git status
# 3. Connect (use YOUR URL)
git remote add origin https://github.com/your-username/my-website.git
git remote -v
# 4. First push
git push -u origin main
# 5. README (create README.md in VS Code first)
git add README.md
git commit -m "Add README describing the site"
git push
# 6. One-time setting
git config --global pull.rebase false
# 7. After editing README.md on GitHub.com
git pull
# 8. Clone a copy next to my-website
cd ..
git clone https://github.com/your-username/my-website.git my-website-copy
cd my-website-copy
git log --oneline
cd ..
cd my-website
Success looks like this: git status says Your branch is up to date with 'origin/main', GitHub shows your README, and the clone's git log --oneline matches your original's.
π Want to go further?
Pair up with a classmate. Clone their public repository into a new folder, open it with Live Server, and look through their git log --oneline. Try to push a small change: Git will refuse, because you don't have permission. Read the error and notice that it's about access, not about your commands. In the next lesson you'll learn the polite way to propose changes: a pull request.
π― Quick Quiz
Question 1: You already have a repository with commits on your laptop. Why should the new GitHub repository be created without a README?
Question 2: What does the -u in git push -u origin main do?
Question 3: Git asks Password for 'https://your-username@github.com': and your GitHub account password is rejected. What's going on?
Question 4: You edited README.md on GitHub.com. On your laptop, git status still says Your branch is up to date with 'origin/main'. Why?
Question 5: What does git clone https://github.com/your-username/my-website.git my-website-copy give you?
π Learning Journal
Take five minutes to add to your learning journal. Write down:
- Key concepts you learned
- What clicked β the idea or technique that made sense
- Questions or confusion, so you know what to revisit
- Ideas to try on your own pages
- How you feel about your progress
βοΈ This lesson's prompt: Explain push, pull, and clone to a friend who has never used Git, using an everyday comparison (a shared photo album, a library, a notebook you photocopy β pick your own). Which of the three felt most natural, and which still feels a little mysterious? What error message did you hit today, and what did it turn out to mean?
Summary
π Key Takeaways
- A remote is another copy of your repository;
originis the usual nickname for the one on GitHub - Create the GitHub repository empty when you're pushing an existing project
git remote add origin β¨urlβ©connects;git remote -vchecksgit push -u origin mainthe first time, then justgit push- Git doesn't take your GitHub password: sign in with Git Credential Manager, VS Code, or
gh auth login git pullbrings down commits made elsewhere; a rejected push means "pull first", never "force"git clonemakes a complete, independent copy with all history- The everyday loop: pull β work β commit β push, and never push secrets
π Additional Resources
- GitHub Docs β Hello World
- GitHub Docs β Adding locally hosted code to GitHub
- GitHub Docs β Caching your GitHub credentials in Git
- GitHub Docs β Basic writing and formatting syntax (Markdown)
- This site β Git in VS Code
π What's Next?
Your site now lives on GitHub. In the final lesson you'll connect Netlify to that repository so every git push updates your live site automatically, and you'll open, preview, and merge your very first pull request.