Git and GitHub for Beginners
Git tracks the history of your files on your own machine; GitHub is a website that hosts copies of Git repositories so you can back them up and share them. They are separate things, and you can use Git for years without ever touching GitHub.
The whole beginner workflow is five commands: git init, git add, git commit, git remote add, git push. Everything else is recovery from mistakes, which is most of what this guide covers.
Most Git tutorials teach the commands and skip the model, which is why people end up typing memorised incantations and panicking when something unexpected happens. This guide explains the three places your work can be, then gives you the commands — and the ones that get you out of trouble.
The three places your work lives
Understanding this makes every command obvious. A file in a Git project is in one of three states:
| Place | What it means | How you got there |
|---|---|---|
| Working directory | The files as they are on disk right now | You edited them |
| Staging area | Changes marked for the next commit | git add |
| Repository | Committed history, permanent | git commit |
The staging area is the part beginners find pointless and experienced users rely on. It lets you commit some of your changes — fix a bug and a typo in one session, commit them separately so the history stays readable.
One-time setup
Install Git from git-scm.com, then tell it who you are. This is stamped on every commit you make:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
Now set the default branch name, and here is why it matters. Run git init without this configured and Git 2.53 still creates a branch called master — verified on a clean install while writing this — while GitHub and virtually every tutorial assume main. That mismatch is a common first stumble.
git config --global init.defaultBranch main
Check what you have set at any time:
git config --global --list
Starting a repository
cd my-project
git init
git status
git status is the command to run constantly. It tells you which of the three places your changes are in and usually suggests the command you want next. Run it after everything until the model is second nature.
The core loop
git add index.html # stage one file
git add . # stage everything changed
git commit -m "Add contact form validation"
git log --oneline # see the history
A commit message should say why, not what — the diff already shows what. "Fix bug" tells your future self nothing; "Reject empty email in contact form" tells them everything.
What not to commit
Create a .gitignore file in the project root before your first commit:
node_modules/
.env
*.log
.DS_Store
dist/
Three rules worth internalising:
- Never commit secrets. API keys, passwords, service-account files. Committing a secret and deleting it in the next commit does not remove it — it stays in history and can be recovered by anyone with the repository. If it happens, treat the key as compromised and rotate it immediately; cleaning history is the secondary step.
- Never commit dependencies.
node_modulesis rebuildable frompackage.jsonand adds tens of thousands of files. - Never commit build output. It is generated, and it creates conflicts on every merge.
.gitignore only affects files Git is not already tracking. If you committed something before ignoring it, remove it from tracking while keeping it on disk:
git rm --cached .env
Connecting to GitHub
Create an empty repository on GitHub — no README, no .gitignore, since you already have those locally — then:
git remote add origin https://github.com/you/repo.git
git branch -M main
git push -u origin main
origin is just a nickname for that URL. -u links your local main to the remote one, so future pushes are only git push.
On authentication: GitHub stopped accepting account passwords for Git operations in 2021. Use a personal access token in place of a password, or set up SSH keys. If a push fails with an authentication error despite a correct password, this is why.
Branches
A branch is a movable pointer to a commit, not a copy of your files — which is why creating one is instant.
git switch -c feature/contact-form # create and switch
git switch main # back to main
git branch # list branches
git merge feature/contact-form # merge into current branch
git switch and git restore replaced the overloaded git checkout, which did both jobs and several others. Older tutorials use checkout everywhere; it still works, but the newer commands are clearer about what they do.
Undoing things — the section you will actually need
This is where beginners freeze. Match the situation to the command:
| Situation | Command |
|---|---|
| Discard changes to a file, not yet staged | git restore file.txt |
| Unstage a file, keep the changes | git restore --staged file.txt |
| Fix the last commit message | git commit --amend |
| Undo last commit, keep the changes | git reset --soft HEAD~1 |
| Undo a commit already pushed | git revert <hash> |
| Set aside work temporarily | git stash then git stash pop |
Two distinctions worth learning properly:
reset versus revert. reset rewrites history and is safe only on commits nobody else has pulled. revert creates a new commit that undoes an old one, leaving history intact — the correct choice for anything already pushed.
--soft versus --hard. git reset --soft keeps your changes; git reset --hard deletes them permanently. --hard is the one command in this guide that genuinely destroys work with no undo. Read it twice before pressing enter.
When you think you have lost something
You usually have not. Git keeps a log of everywhere HEAD has pointed, including commits no branch references any more:
git reflog
Find the hash from before the mistake and return to it:
git reset --hard <hash>
This recovers from a bad reset, a deleted branch, or a rebase that went wrong. Anything committed at any point is almost certainly still recoverable for weeks. Work that was never committed is not — which is the practical argument for committing often.
Working with others
git pull # fetch and merge their changes
git push # send yours
Pull before you start work and before you push. A merge conflict happens when two people changed the same lines; Git marks them in the file:
<<<<<<< HEAD
your version
=======
their version
>>>>>>> branch-name
Edit the file so it reads how you want, delete all three marker lines, then git add and git commit. Conflicts are routine, not a failure — but a conflicted file left with markers in it will happily be committed and break your build, so search for <<<< before committing.
Frequently asked questions
What is the difference between Git and GitHub?
Git is version-control software that runs on your computer and tracks file history. GitHub is a commercial website that hosts Git repositories online for backup and collaboration. Git works entirely offline; GitHub is one of several hosts, alongside GitLab and Bitbucket.
Why does git init create a branch called master and not main?
Because that is still Git's built-in default when you have not configured otherwise — confirmed on Git 2.53. GitHub uses main, so set git config --global init.defaultBranch main once and new repositories will match.
How do I undo the last commit?
If it is not pushed, git reset --soft HEAD~1 removes the commit and keeps your changes staged. If it is already pushed, use git revert <hash> instead, which records a new commit undoing it rather than rewriting shared history.
What does git add actually do?
It copies the current state of a file into the staging area, marking it for the next commit. Editing the file after staging means you have to git add again — the staged snapshot is the version at the moment you added it.
I committed a password. Is deleting it enough?
No. Removing it in a later commit leaves it in history, where anyone with the repository can recover it. Rotate the credential immediately — assume it is compromised — and then clean the history separately with a tool such as git-filter-repo.
What is a merge conflict?
It occurs when two branches change the same lines and Git cannot decide which to keep. It marks both versions in the file between <<<<<<<, ======= and >>>>>>>. Edit the file to the version you want, delete the markers, then add and commit.
Conclusion
Git makes sense once you hold the three-places model: working directory, staging area, repository. Every command moves changes between them, and git status tells you where things are whenever you lose the thread.
Commit early and often — it costs nothing and it is what makes reflog able to save you. The only work Git cannot recover is work you never committed.
If you are setting up a development machine from scratch, our guide to installing Python on Windows covers the other half of a typical beginner setup, and Python projects for beginners gives you something worth putting under version control. If you are building for the web, building a unit converter in JavaScript is a small project that fits in a single repository.
Comments