A beginner-friendly guide to understanding Git and tracking your code changes like a pro
Git is a version control system that tracks changes to your files over time. Think of it as a time machine for your code â you can save snapshots, go back to any previous state, experiment with new features without breaking anything, and collaborate with others seamlessly.
| Scenario | Without Git | With Git |
|---|---|---|
| Bug in production | Panic, manually search through files, pray you remember what changed | git bisect â find the exact commit that introduced the bug |
| Experiment with a new feature | Copy the whole folder, work in isolation, manually merge later | git checkout -b feature-x â branch, experiment, merge when ready |
| Collaborate with a teammate | Email zip files, use USB drives, overwrite each other's work | git push / git pull â everyone syncs to the same repository |
| Git | GitHub |
|---|---|
| A tool â the version control software itself | A platform â a website that hosts Git repositories |
| Runs locally on your machine | Runs in the cloud (like a social network for code) |
| Like a camera that takes snapshots | Like Instagram where you share those snapshots |
| Works offline â no internet needed | Needs internet to push/pull code |
| Alternatives: none (Git is standard) | Alternatives: GitLab, Bitbucket, Gitea |
| Concept | What it is |
|---|---|
| Repository (repo) | A folder tracked by Git â contains all files + the .git history database |
| Commit | A snapshot of your files at a point in time â like a save point |
| Branch | A movable pointer to a commit â lets you diverge from the main line of work |
| Working Directory | The files you see and edit on your machine |
| Staging Area (index) | A middle ground â files you've told Git to include in the next commit |
| HEAD | A pointer to your current position â usually the latest commit on your current branch |
| Remote | A copy of the repo hosted elsewhere (e.g., GitHub) |
Every file in a Git repo can be in one of three states:
# File lifecycle in Git Untracked â a new file Git doesn't know about yet Modified â you changed the file but haven't staged it yet Staged â you marked the file to be included in the next commit Committed â the file is safely saved in Git's history
Analogy â Packing for a Trip:
reset or revert)Here's how a typical Git session looks, step by step:
# 1. Initialize a new repo (or clone an existing one) $ git init # or $ git clone https://github.com/user/repo.git # 2. Check what's changed $ git status # 3. Stage files for commit $ git add index.html # stage a specific file $ git add . # stage all changes # 4. Commit the staged snapshot $ git commit -m "Add landing page hero section" # 5. Push to remote (if you have one) $ git push origin main
git init / git clone
git init creates a new empty Git repository in your current folder.
git clone downloads an existing repository from a remote (like GitHub) including its full history.
Analogy: git init is buying a fresh notebook. git clone is photocopying someone else's filled notebook.
git statusShows the current state of your working directory and staging area. It tells you which files are modified, staged, or untracked.
Most used Git command â run it constantly to see where you are.
git addMoves changes from your working directory into the staging area. You decide which changes go into the next commit.
Analogy: You're a photographer picking which photos to put in an album. git add is selecting a photo and placing it on the "to-print" pile.
git commitTakes everything in the staging area and creates a permanent snapshot (commit) in Git's history. Each commit has a unique ID (SHA hash) and your message describing what changed.
Write good commit messages! They're notes to your future self (and your teammates).
| Bad commit message | Good commit message |
|---|---|
fixed stuff | fix: prevent crash when user submits empty form |
update | feat: add user avatar upload to profile page |
git pushUploads your local commits to a remote repository (e.g., GitHub) so others can see them.
Analogy: You've written diary entries locally. git push is mailing a copy to your friend.
Branches let you work on multiple versions of your code simultaneously.
The default branch is usually called main (or master on older repos).
main). A branch grows out from the trunk, adding leaves and fruit
(new features) without affecting the rest of the tree. Once the branch is healthy and ready,
you can merge it back into the trunk.
# Create and switch to a new branch $ git checkout -b feature-dark-mode # Work, stage, commit as usual... $ git add . && git commit -m "feat: add dark mode toggle" # Switch back to main $ git checkout main # Merge your feature branch into main $ git merge feature-dark-mode # Delete the branch (cleanup after merge) $ git branch -d feature-dark-mode
Note: git checkout is a bit of an "everything" command â it switches branches
and restores files, which can be confusing. Since Git 2.23, you can use the more explicit
git switch -c feature-dark-mode (create/switch branches) and git restore <file>
(discard file changes) instead. Both styles work fine â checkout just does more than one job.
When two branches modify the same part of the same file, Git can't decide which change to keep. This is a merge conflict. Git marks the conflict in the file, and you resolve it manually.
# Git marks conflicts like this in the file: <<<<<<< HEAD console.log("dark mode enabled"); ======= console.log("theme: dark"); >>>>>>> feature-dark-mode # Fix the file, then: $ git add index.js $ git commit -m "fix: resolve dark mode merge conflict"
Tip: Conflicts aren't scary! They're Git being honest â it's telling you "I need your human judgment here." Open the file, pick the right code (or combine both), and commit.
Git commands themselves (git add, git commit, etc.) are identical on every OS â
Git behaves the same on Windows, macOS, and Linux. What differs is the shell you type them into,
which affects things like chaining commands together and file paths. The steps below show the Git commands once,
with a callout wherever the surrounding shell syntax changes.
On Windows: installing Git also installs Git Bash, a Unix-like terminal.
Using Git Bash means every command below (including && chaining) works exactly like on macOS/Linux â
it's the easiest option for beginners. PowerShell and Command Prompt (cmd) also work, just with the differences noted below.
# Linux (Ubuntu/Debian) sudo apt install git # macOS brew install git # Windows â winget (built into Windows 10/11), or download the installer winget install --id Git.Git -e --source winget # or download from https://git-scm.com â this also installs Git Bash
git config --global user.name "Your Name" git config --global user.email "[email protected]"
This stamps your name on every commit. Same command on every OS.
git config --global init.defaultBranch main
Without this, git init still creates a branch called master on most installs, even though
GitHub calls its default branch main. Setting this once avoids a mismatch later when you push.
# macOS / Linux / Windows Git Bash / Windows cmd â all support && mkdir my-cool-project && cd my-cool-project git init # Windows PowerShell (older versions don't support &&) â use separate lines or ; instead: mkdir my-cool-project cd my-cool-project git init
echo "# My Cool Project" > README.md git add README.md git commit -m "chore: initial commit with README"
echo ... > README.md works the same in Bash, cmd, and PowerShell.
git remote add origin https://github.com/yourname/my-cool-project.git git push -u origin main
If you skipped step 3 (or are working in an existing repo created before you set init.defaultBranch),
rename the branch first: git branch -M main.
# macOS / Linux / Git Bash / cmd git add . && git commit -m "your message" git push # PowerShell (if && isn't supported in your version, split into two lines) git add . git commit -m "your message" git push
One of Git's superpowers: you can undo almost anything.
| Command | What it does |
|---|---|
git restore <file> | Discard unstaged changes in a file (revert to last commit) |
git restore --staged <file> | Unstage a file (keep changes, just remove from staging) |
git commit --amend -m "new message" | Change the last commit's message or add forgotten files |
git reset --soft HEAD~1 | Undo last commit but keep changes staged |
git reset --hard HEAD~1 | Undo last commit and discard its changes â ī¸ |
git revert <commit-hash> | Create a new commit that undoes a previous commit (safe for shared branches) |
git reset --hard discards changes immediately and should be used carefully.
It's usually recoverable â Git keeps discarded commits in the reflog for about 90 days, so
git reflog followed by git reset --hard <old-hash> can often bring them back. But don't
count on it as a safety net â for anything already pushed and shared, use git revert instead.
Rewriting shared history confuses your teammates.
.gitignore File
A .gitignore file tells Git which files to ignore â things like
credentials, dependencies, build outputs, and OS junk. Place it in the root of your repo.
# .gitignore â patterns Git will skip # Dependencies node_modules/ vendor/ # Build output dist/ build/ *.pyc # Environment files (contain secrets!) .env .env.local # OS files .DS_Store Thumbs.db # IDE config .vscode/ .idea/ # Logs *.log
Always commit .gitignore before adding sensitive files! If you accidentally commit a secret, change the secret immediately â it's already in Git's history.
| Command | What it does |
|---|---|
git init | Create a new Git repository |
git clone <url> | Download a remote repository |
git status | Show current state of working directory |
git add <file> | Stage changes for commit |
git commit -m "msg" | Commit staged changes |
git log --oneline | View commit history (compact) |
git diff | Show unstaged changes |
git branch | List branches (* = current) |
git checkout -b <name> | Create and switch to a new branch |
git merge <branch> | Merge a branch into the current one |
git push | Upload commits to remote |
git pull | Download and integrate remote changes |
git stash | Temporarily save uncommitted changes |
feat:, fix:, chore:, docs:, etc.
main. Create a branch for every bug or feature.
.gitignore for .env files. Rotate any accidentally exposed secrets immediately.
git pull first to avoid unnecessary merge conflicts.
.gitignore early
Remember: Git turns chaos into history. Every commit is a save point, every branch is a safe sandbox.
Learn the basics, and you'll never fear breaking your code again.
Created by jcmatira