Git & GitHub β€” Beginner's Reference

Git & GitHub for Beginners

A practical, example-driven reference. Learn what version control is, how the Git workflow actually feels, and what all those words (origin, HEAD, rebase, PR) mean.

1. What is Git?

Git is a distributed version control system (DVCS). It records snapshots of your project over time so you can:

  • See exactly what changed, when, and by whom.
  • Go back to any previous state.
  • Work on several ideas in parallel without breaking the main code.
  • Combine work from multiple people.

Git runs entirely on your computer. GitHub is a website that hosts Git repositories and adds collaboration features on top. You can use Git without GitHub, but GitHub is useless without Git.

GitGitHub
What it isA program on your machineA website / cloud service
JobTracks versions of filesStores repos, hosts collaboration
Works offline?Yes, fullyNo
Made byLinus Torvalds (2005)GitHub Inc. (now Microsoft)
AlternativesMercurial, SVN, FossilGitLab, Bitbucket, Codeberg
Mental model

Git is a chain of snapshots, not a list of file differences. Each snapshot (a commit) points back to its parent, forming a history graph. A branch is just a movable label pointing at one commit in that graph.

2. The Three Areas

Almost every confusing thing about Git disappears once you understand that your work lives in three places.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” git add β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” git commit β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Working Tree β”‚ ───────────► β”‚ Staging Area β”‚ ─────────────► β”‚ Repository β”‚ β”‚ (your files) β”‚ β”‚ (the index) β”‚ β”‚ (.git history) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β–² β”‚ β”‚ β”‚ git restore β”‚ git restore --staged β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ git checkout / git switch
AreaAlso calledWhat lives there
Working tree working directory, workspace The actual files you edit in your editor.
Staging area index, stage, cache Changes you've marked to go into the next commit.
Repository history, .git, object database All commits ever made. Stored in the hidden .git folder.
Why stage at all?

Staging lets you commit only some of your changes. You might fix a bug and rename a file in the same editing session β€” stage and commit them separately so history stays readable.

3. First-Time Setup

Install Git, then tell it who you are. This is done once per machine.

# Identity β€” attached to every commit you make
git config --global user.name "Ada Lovelace"
git config --global user.email "ada@example.com"

# Name the default branch "main" instead of "master"
git config --global init.defaultBranch main

# Nicer output
git config --global color.ui auto
git config --global pull.rebase false

# Verify everything
git config --list

# Where does Git look for settings? (--global = ~/.gitconfig)
git config --list --show-origin

Connecting to GitHub over SSH (recommended)

# 1. Create a key pair
ssh-keygen -t ed25519 -C "ada@example.com"
# Press Enter for the default path, then set a passphrase

# 2. Copy the PUBLIC key
cat ~/.ssh/id_ed25519.pub

# 3. Paste it into GitHub β†’ Settings β†’ SSH and GPG keys β†’ New SSH key

# 4. Test the connection
ssh -T git@github.com
Never share your private key

The file id_ed25519 (no .pub) is private. Only id_ed25519.pub goes to GitHub.

4. Starting a Repo

Option A β€” Create a brand new repository

mkdir my-project
cd my-project
git init
# Initialized empty Git repository in /path/my-project/.git/

echo "# My Project" > README.md
git add README.md
git commit -m "Initial commit"

Option B β€” Copy an existing repository

# HTTPS (asks for a token)
git clone https://github.com/octocat/Hello-World.git

# SSH (uses your key)
git clone git@github.com:octocat/Hello-World.git

# Clone into a specific folder name
git clone git@github.com:octocat/Hello-World.git my-folder

# Shallow clone β€” faster, no full history
git clone --depth 1 git@github.com:octocat/Hello-World.git

git clone does four things: downloads the history, creates a remote named origin pointing at the URL, checks out the default branch, and sets up tracking.

5. The Daily Loop

This is 90% of what you'll ever type:

# 1. See where you are and what's changed
git status

# 2. Look at the actual changes
git diff                 # unstaged changes
git diff --staged        # what's about to be committed

# 3. Stage what you want in the next commit
git add file.txt         # one file
git add src/             # a folder
git add .                # everything in the current dir
git add -p               # choose changes hunk by hunk (very useful)

# 4. Save the snapshot
git commit -m "Add login form validation"

# 5. Send it to GitHub
git push

Reading the log

git log
git log --oneline
git log --oneline --graph --decorate --all
git log -p                     # with full diffs
git log --author="Ada"
git log --since="2 weeks ago"
git log -- src/app.js          # history of one file
git show a1b2c3d               # inspect one commit
git blame src/app.js           # who last touched each line
Anatomy of a commit

Every commit stores: a SHA hash (its ID), the author, the timestamp, a message, a pointer to its parent commit, and a snapshot of the whole tree. The SHA is derived from all of that β€” change anything and the ID changes.

Writing a good commit message

# Bad
git commit -m "fix stuff"

# Good β€” imperative mood, explains WHY
git commit -m "Fix crash when email field is empty"

# Better β€” short subject + blank line + body
git commit -m "Fix crash when email field is empty" \
           -m "The validator assumed a non-null value. Added a guard and
a regression test in tests/validation.test.js."

Convention: subject line ≀ 50 characters, imperative mood ("Add", "Fix", "Remove" β€” not "Added" or "Fixes").

6. Branching & Merging

A branch is a lightweight, movable pointer to a commit. Creating one costs nothing and takes no time β€” so create them liberally.

main: A ── B ── C ────────────── M ← merge commit \ / feature: D ── E β”€β”€β”€β”€β”€β”€β”˜

Working with branches

git branch                          # list local branches
git branch -a                       # list local + remote
git branch -v                       # with last commit

git switch -c feature/login         # create AND switch
git switch main                     # go back to main

# Older syntax (still works everywhere)
git checkout -b feature/login
git checkout main

git branch -d feature/login         # delete (safe: only if merged)
git branch -D feature/login         # force delete
git branch -m new-name              # rename current branch

Merging

# Bring feature work into main
git switch main
git merge feature/login

# Two possible outcomes:
#   Fast-forward  β†’ main just slides forward, no merge commit
#   Three-way     β†’ Git creates a merge commit

# Force a merge commit even when fast-forward is possible
git merge --no-ff feature/login

# Undo a merge you haven't pushed
git merge --abort

Merge conflicts

A conflict happens when both branches changed the same lines. Git marks the file and stops:

<<<<<<< HEAD
const timeout = 3000;
=======
const timeout = 5000;
>>>>>>> feature/login

To resolve:

  1. Open the file and edit it into the version you want.
  2. Delete the <<<<<<<, =======, and >>>>>>> markers.
  3. git add <file>
  4. git commit (Git pre-fills the merge message).
git status                  # "Unmerged paths" lists conflicted files
git diff                    # shows conflict markers
# ...edit files...
git add .
git commit
# Or bail out entirely:
git merge --abort

Rebase β€” the alternative to merging

# Replay your branch's commits on top of the latest main
git switch feature/login
git rebase main

# Interactive: reorder, edit, squash, drop commits
git rebase -i HEAD~3

# If it goes wrong
git rebase --abort
git rebase --continue
The golden rule of rebase

Never rebase commits that others have already pulled. Rebase rewrites history (new SHAs); merge preserves it. Rebase your own unpushed work only.

7. GitHub & Remotes

A remote is a named URL to another copy of the repo. The default name is origin.

# See your remotes
git remote -v

# Add one
git remote add origin git@github.com:ada/my-project.git

# Change where origin points
git remote set-url origin git@github.com:ada/renamed.git

# Remove one
git remote remove origin

Push, fetch, pull

# First push of a new branch: -u sets the upstream tracking link
git push -u origin main
# After that, plain "git push" knows where to go
git push

# Push a different branch
git push origin feature/login

# Delete a remote branch
git push origin --delete feature/login

# Download remote changes WITHOUT touching your files
git fetch
git fetch --all --prune

# Download AND integrate into your current branch
git pull
# git pull = git fetch + git merge (or + git rebase)

# Pull with rebase to keep history linear
git pull --rebase
CommandDownloads?Changes your files?
git fetchYesNo β€” safe to run anytime
git pullYesYes β€” merges into current branch
git pushUploadsNo (changes the remote)

Fork vs. clone vs. branch

TermWhereWhat it means
ForkGitHub (server-side) Your own copy of someone else's repository under your account.
CloneYour machine Downloading a repository so you can work on it locally.
BranchInside one repo A parallel line of development within the same repository.

To contribute to a project you don't own: fork it β†’ clone your fork β†’ create a branch β†’ commit β†’ push β†’ open a pull request.

# Keep your fork in sync with the original project
git remote add upstream git@github.com:original-owner/project.git
git fetch upstream
git switch main
git merge upstream/main
git push origin main

8. The Pull Request Flow

A Pull Request (PR) is a GitHub feature, not a Git one. It says: "here's a branch of mine; please review it and merge it into yours."

  1. Branch off the latest main.
    git switch main
    git pull
    git switch -c fix/empty-email
  2. Commit your work in small, logical chunks.
    git add src/validator.js tests/validator.test.js
    git commit -m "Guard against empty email in validator"
  3. Push the branch.
    git push -u origin fix/empty-email
  4. Open the PR on GitHub. Fill in what changed and why.
  5. Respond to review β€” push more commits to the same branch; the PR updates automatically.
  6. Merge via the GitHub button, then clean up.
    git switch main
    git pull
    git branch -d fix/empty-email

Merge strategies on GitHub

StrategyResult
Merge commitKeeps every commit plus a merge commit. Full history.
Squash and mergeCombines all PR commits into one. Clean main history.
Rebase and mergeReplays commits onto main with no merge commit. Linear.
Small PRs win

A 50-line PR gets a careful review in 10 minutes. A 2,000-line PR gets "LGTM" and a prayer. Keep them small.

9. Undoing Things

Git almost never loses data β€” but it helps to know which tool to reach for.

I want to…CommandSafe?
Discard changes in a file (not staged) git restore file.txt ⚠️ Destructive β€” no undo
Unstage a file (keep the changes) git restore --staged file.txt βœ… Safe
Fix the last commit message git commit --amend -m "New message" ⚠️ Rewrites history
Add a forgotten file to the last commit git add file && git commit --amend --no-edit ⚠️ Rewrites history
Undo last commit, keep changes staged git reset --soft HEAD~1 βœ… Safe
Undo last commit, keep changes unstaged git reset HEAD~1 βœ… Safe
Nuke the last commit and all its changes git reset --hard HEAD~1 πŸ›‘ Very destructive
Undo a commit that's already pushed git revert <sha> βœ… Safe β€” makes a new commit
Park work temporarily git stash / git stash pop βœ… Safe
Recover something you thought was lost git reflog βœ… Read-only

reset vs. revert

  • reset moves your branch pointer backwards and erases commits from the branch. Use on local, unpushed work.
  • revert creates a new commit that undoes an old one. Use on anything already shared.

Stashing

git stash                       # save & clean working tree
git stash push -m "wip: login"  # with a label
git stash -u                    # include untracked files
git stash list
git stash pop                   # reapply and remove from stash
git stash apply stash@{2}       # reapply but keep in stash
git stash drop stash@{0}
git stash clear                 # delete all stashes

The reflog β€” your safety net

git reflog
# a1b2c3d HEAD@{0}: commit: Fix typo
# 9f8e7d6 HEAD@{1}: reset: moving to HEAD~1

# Recover the "lost" commit
git switch -c rescue 9f8e7d6
# or
git reset --hard 9f8e7d6
Reflog = reference log

Git records every place HEAD has been for ~90 days, even commits that no longer belong to any branch. Almost nothing is truly unrecoverable.

Force pushing, safely

# After amending or rebasing a pushed branch
git push --force-with-lease
# Safer than --force: refuses if someone else pushed in the meantime

10. .gitignore & Good Habits

A .gitignore file at the repo root lists patterns Git should pretend don't exist.

# Dependencies
node_modules/
vendor/

# Build output
dist/
build/
*.min.js

# Environment & secrets β€” NEVER commit these
.env
.env.local
*.pem

# Editor / OS cruft
.vscode/
.idea/
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*

# Negate: keep this one even though *.log is ignored
!important.log

If you already committed a file you now want ignored

git rm --cached .env          # untrack it, keep it on disk
git rm -r --cached node_modules
echo ".env" >> .gitignore
git commit -m "Stop tracking .env"
If you leak a secret

Adding it to .gitignore afterwards is not enough β€” it's still in history. Rotate the credential immediately, then rewrite history with a tool like git-filter-repo or BFG Repo-Cleaner.

Habits worth building

  • Commit often, commit small. One logical change per commit.
  • Pull before you start. git pull --rebase on main.
  • Branch for everything. Never commit straight to main on a shared repo.
  • Run git status constantly. It tells you what Git thinks is happening.
  • Write messages for future-you, who will have forgotten everything.
  • Never commit secrets, large binaries, or node_modules.

11. Command Cheat Sheet

Setup

git config --global user.name "N"Set your name
git config --global user.email "E"Set your email
git config --listShow all settings

Create & copy

git initStart a new repo here
git clone <url>Copy a remote repo locally

Inspect

git statusCurrent state of the three areas
git diffUnstaged changes
git diff --stagedStaged changes
git log --oneline --graph --allCompact visual history
git show <sha>Details of one commit
git blame <file>Who changed each line
git reflogEverywhere HEAD has been

Change

git add <file>Stage a file
git add -pStage interactively, hunk by hunk
git commit -m "msg"Commit staged changes
git commit --amendRewrite the last commit
git rm <file>Delete and stage the deletion
git mv a bRename/move and stage it

Branch & merge

git branchList branches
git switch -c <name>Create and switch
git switch <name>Switch branch
git merge <branch>Merge into current branch
git rebase <branch>Replay commits on top of another
git cherry-pick <sha>Copy one commit here
git branch -d <name>Delete merged branch

Share

git remote -vList remotes
git fetchDownload, don't merge
git pullDownload and merge
git pushUpload commits
git push -u origin <branch>Push and set upstream
git push --force-with-leaseForce push, safely

Undo

git restore <file>Discard file changes
git restore --staged <file>Unstage
git reset --soft HEAD~1Uncommit, keep staged
git reset --hard HEAD~1Uncommit and delete changes
git revert <sha>Undo a pushed commit safely
git stash / git stash popPark / restore work

12. Common Errors & What They Mean

fatal: not a git repository
You're in a folder that isn't a repo (or a subfolder of one). cd into the project or run git init.
Please tell me who you are
Git needs an identity. Run the git config --global user.name and user.email commands from Β§3.
Updates were rejected because the remote contains work that you do not have
Someone pushed before you. git pull --rebase, resolve any conflicts, then git push.
CONFLICT (content): Merge conflict in <file>
Two branches changed the same lines. Edit the file, remove the <<< / === / >>> markers, git add, git commit.
Your local changes would be overwritten by merge
You have uncommitted edits that clash. Commit them, or git stash first, then pull, then git stash pop.
detached HEAD
You checked out a specific commit or tag rather than a branch. You can look around, but new commits won't belong to any branch. Fix with git switch main or git switch -c new-branch.
Permission denied (publickey)
GitHub doesn't recognize your SSH key. Check ssh -T git@github.com, make sure your public key is uploaded and your remote URL uses git@github.com:….
remote: Support for password authentication was removed
GitHub no longer accepts account passwords over HTTPS. Use SSH, or a Personal Access Token (PAT) as the password.

13. Glossary

Core concepts

Repository repo
A project tracked by Git β€” the files plus the entire history in .git/.
Working tree (a.k.a. working directory)
The files as they currently exist on disk, which you edit directly.
Index (a.k.a. staging area, stage, cache)
The middle ground where you assemble the next commit. git add writes here.
Commit
A permanent snapshot of the whole project plus metadata (author, message, parent). Identified by a SHA hash.
SHA (a.k.a. hash, object ID)
The 40-character hex ID of a commit or object, e.g. a1b2c3d…. Usually abbreviated to the first 7–10 characters.
Branch
A movable pointer to a commit. Not a copy of files β€” just a label. main is the conventional primary branch.
HEAD
A pointer to "where you are right now" β€” normally the tip of the branch you have checked out.
Detached HEAD
HEAD points directly at a commit instead of a branch. New commits here belong to nothing.
Remote
A named reference to another copy of the repo, usually on a server. The default is origin.
origin
The conventional name of the remote you cloned from. Just a nickname β€” you can rename it.
upstream
Two meanings: (1) the remote branch your local branch tracks; (2) in forking workflows, the original repo you forked from.
Tracking branch
A local branch linked to a remote branch, so git push and git pull work with no arguments.
Clone
A full local copy of a remote repository, including history.
Fork
A server-side copy of someone else's repo into your own GitHub account.
Merge
Combining the histories of two branches into one.
Fast-forward
A merge where the target branch has no new commits, so Git just slides the pointer forward. No merge commit is created.
Merge conflict
Git can't automatically combine changes because both sides edited the same lines. You resolve it by hand.
Rebase
Replaying your commits on top of another branch to create a linear history. Rewrites commit SHAs.
Cherry-pick
Copying a single commit from one branch onto another.
Stash
A temporary shelf for uncommitted changes, so you can switch context cleanly.
Tag
A permanent label on a specific commit, typically used for releases, e.g. v1.2.0.
Diff
The line-by-line difference between two states of a file.
Hunk
A contiguous block of changed lines inside a diff. git add -p works hunk by hunk.
HEAD~1 / HEAD^
Shorthand for "the commit one step before HEAD". HEAD~3 = three commits back.
Reflog
Git's local log of every place HEAD and branches have pointed. Your recovery tool.
Detached / dirty working tree
"Dirty" means you have uncommitted changes. "Clean" means everything is committed.
.gitignore
A file listing paths Git should never track.

GitHub terms

Pull Request PR
A GitHub request to merge one branch into another, with review and discussion attached. GitLab calls it a Merge Request (MR).
Issue
A GitHub thread for reporting a bug, requesting a feature, or discussing a task.
Review
Feedback on a PR. Reviewers can Comment, Approve, or Request Changes.
Actions
GitHub's built-in CI/CD system. YAML files in .github/workflows/ define automated jobs.
Pages
Free static website hosting straight from a repo.
Release
A tag plus release notes and optional downloadable assets.
Gist
A shareable single-file or snippet repository.
Personal Access Token PAT
A scoped, revocable token used instead of a password over HTTPS.
Protected branch
A branch with rules β€” e.g. "no direct pushes to main" and "require one approval".
CODEOWNERS
A file that auto-assigns reviewers based on which paths a PR touches.

Idioms & slang you'll hear

"Commit early, commit often"
Frequent small commits beat one giant commit. Easier to review, revert, and understand.
"Atomic commit"
A commit that does exactly one logical thing and leaves the project in a working state.
"Bikeshedding"
Arguing at length about trivial details (naming, formatting) while ignoring the hard problems.
"Nit"
A minor, optional review comment β€” "nit: this variable name could be clearer". Not a blocker.
"LGTM"
"Looks Good To Me" β€” approval in review slang.
"WIP"
"Work In Progress" β€” a branch or PR that isn't ready to merge.
"The golden rule of rebase"
Never rebase commits that have already been pushed and shared.
"Force push with lease"
Using --force-with-lease instead of --force, so you won't clobber a teammate's work.
"Merge hell"
A huge, painful conflict caused by long-lived branches diverging too far from main.
"YOLO merge"
Merging without reading the diff. Don't.
"Blame"
git blame shows which commit last changed each line. It's a diagnostic tool, not an accusation.
"Bisect"
git bisect binary-searches your history to find which commit introduced a bug.
"Clean tree"
git status reports nothing to commit. A nice place to be before switching branches.
"History rewrite"
Changing existing commits β€” via amend, rebase, or filter-repo. Changes SHAs.
"Squash"
Combining several commits into one, usually right before merging a PR.
"The sacred main branch"
The half-joking idea that main must always be deployable and never receive direct pushes.
"Working on a dirty tree"
Having uncommitted changes while trying to switch branches β€” a common source of confusion.

14. Acronyms

AcronymStands forMeaning in context
VCSVersion Control SystemSoftware that tracks file history.
DVCSDistributed Version Control SystemEvery clone has the full history β€” Git is one.
SCMSource Control ManagementAnother name for version control tooling.
SHASecure Hash AlgorithmThe commit ID hash, e.g. a1b2c3d.
HEADβ€” (not an acronym)Pointer to your current commit/branch.
PRPull RequestGitHub's merge proposal + review thread.
MRMerge RequestGitLab's equivalent of a PR.
CIContinuous IntegrationAutomatically building and testing every push.
CDContinuous Delivery / DeploymentAutomatically shipping tested code.
SSHSecure ShellKey-based authentication method for Git.
PATPersonal Access TokenPassword replacement for HTTPS Git operations.
2FATwo-Factor AuthenticationRequired for GitHub accounts; forces PATs over HTTPS.
LGTMLooks Good To MeReviewer approval shorthand.
WIPWork In ProgressNot ready to merge.
OSSOpen Source SoftwarePublicly licensed, community-developed code.
CLICommand-Line InterfaceUsing Git in a terminal.
GUIGraphical User InterfaceGitHub Desktop, GitKraken, VS Code's Git panel, etc.
LFSLarge File StorageGit extension for big binaries (images, video, datasets).
YAMLYAML Ain't Markup LanguageConfig format used by GitHub Actions workflows.
MIT / GPL / Apacheβ€”Common open-source license types.
Where to go next

Official book: Pro Git (free at git-scm.com/book) Β· Interactive practice: Learn Git Branching Β· Docs: docs.github.com Β· Quick help: git help <command> or git <command> --help.