Setup & Cloning
Getting Git ready and grabbing your first repository
git config
▼
Set your identity
Tell Git who you are before your first commit
Before you do anything, Git needs to know your name and email so it can stamp your work with your identity. Every commit you create will carry this information. It's just like signing your name on a document.
Think of it like filling out your name badge at a conference. You only do it once, and then everyone knows who you are at every event (commit) you attend.
$ git config --global user.name "Your Name"
$ git config --global user.email "you@example.com"
# Check what you set
$ git config --list
Use the same email address as your GitHub account. That's how GitHub links your commits to your profile and contribution graph.
git init
▼
Create a new repository
Turn any folder into a Git-tracked project from scratch
git init sets up a brand-new Git repository inside your current folder. It creates a hidden .git folder that Git uses to track every change you ever make.
Imagine opening a fresh binder and putting a set of divider tabs in it. Nothing is filed yet, but the binder is ready to track everything you put in it going forward.
# Go into your project folder first
$ cd my-project
$ git init
Initialized empty Git repository in /my-project/.git/Real-world scenarios
1
You just started a new website and want to start tracking changes: cd website-folder && git init
2
You finished prototyping a script and now want a proper history before sharing it with a teammate.
git clone
▼
Download an existing repository
Copy a GitHub project to your computer
git clone makes a full copy of a repository from GitHub (or any remote) onto your machine — including all files, history, and branches. It's the standard first step for contributing to an existing project.
It's like downloading a zip of the project, except you also get the complete filing cabinet of every change ever made, and a live connection back to the original.
# Clone into a new folder named after the repo
$ git clone https://github.com/user/repo-name.git
# Clone into a folder with a custom name
$ git clone https://github.com/user/repo-name.git my-folderReal-world scenarios
1
You found an open-source tool on GitHub and want to run it locally or fix a bug: clone it, then work in your copy.
2
A coworker shared a repo link and you need to get the project running on your laptop before tomorrow's meeting.
Checking the Status
Always know what's going on before you do anything
git status
▼
See what's changed
Your most-used command; Run it often
git status gives you a snapshot of your current situation: which files are new, which have been modified, which are staged and ready to commit, and what branch you're on. It never changes anything, it only reports.
Think of it as glancing at your desk before leaving the office. You're checking: what's still out? what got filed? what needs to be dealt with before you go?
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
modified: index.html
Untracked files:
(use "git add <file>..." to include in what will be committed)
style.css
Make
git status a reflex. Run it before staging, before committing, before switching branches, it takes half a second and prevents most beginner mistakes.
git diff
▼
See exactly what changed
Line-by-line comparison of your edits
While
git status tells you which files changed, git diff shows you precisely what changed inside them, line by line. Lines starting with + were added, lines with - were removed.
# See all unstaged changes
$ git diff
# See changes already staged for commit
$ git diff --staged
# Compare two branches
$ git diff main feature-branchReal-world scenarios
1
You edited a config file and can't remember what you changed, git diff config.yaml shows the exact lines.
2
Before committing, run git diff --staged to review everything one last time so your commit message can be accurate.
Staging & Committing
Saving your work to Git's history; The core workflow
git add
▼
Stage files for a commit
Choose what goes into your next save point
Before Git saves anything, you have to deliberately choose which changes to include.
git add moves files into a "staging area", a draft zone where you assemble the perfect commit before locking it in.
Picture a shopping cart.
git add puts items in the cart. You haven't bought anything yet, so you can still swap things out. git commit (next) is when you actually check out.
# Stage a specific file
$ git add index.html
# Stage all changed files at once
$ git add .
# Stage all .js files
$ git add *.js
# Interactively choose which parts of a file to stage
$ git add -p script.jsgit add . stages everything in the folder. That's usually fine, but watch out for accidentally staging temporary files, passwords, or large binaries. A .gitignore file (below) prevents those from being tracked.
git commit
▼
Save a snapshot of your work
Create a permanent entry in your project's history
A commit is a permanent snapshot of your staged changes, stamped with your name, the date, and a message you write. Every commit is forever preserved in the project history.
A commit is like taking a photo of your work. No matter how much things change afterward, you can always pull out that photo and see exactly what it looked like at that moment.
# The standard commit with a message
$ git commit -m "Add navigation menu to header"
# Stage all tracked files and commit in one step
$ git commit -am "Fix typo in homepage copy"Writing a good commit message
✔
"Add user login form with email validation". Clear, describes what changed and why
✘
"stuff" or "changes" is Useless in 6 months when you're trying to find a bug
Aim to commit one logical change at a time. Small, focused commits are much easier to review, revert, or understand later.
.gitignore
▼
Tell Git what to ignore
Keep junk, secrets, and build artifacts out of your repo
A
.gitignore file is a plain text list of file patterns you never want Git to track. It lives in your project root and prevents things like passwords, auto-generated folders, or your personal editor settings from accidentally ending up in commits.
It's like telling the movers "don't pack the junk drawer." You're setting rules upfront so those things never make it into the truck.
# Example .gitignore file
node_modules/ # JS dependencies (huge, auto-downloaded)
.env # Environment variables / API keys
*.log # Any log file
dist/ # Build output
.DS_Store # macOS folder metadata
Visit gitignore.io and type in your language or framework to instantly generate a solid
.gitignore file.
Viewing History
Explore what happened and when
git log
▼
Browse commit history
See every saved snapshot in order
git log lists every commit ever made to the current branch, with the author, date, and message for each. It's the project's complete diary.
# Full log
$ git log
# Compact one-liner format (highly recommended)
$ git log --oneline
a3f21bc Fix broken link in footer
7c4d9a1 Add contact page
2e18f00 Initial commit
# Visual branch graph
$ git log --oneline --graph --all
# Show last 5 commits only
$ git log -5
Press
q to quit the log view. Use the arrow keys or spacebar to scroll through long histories.
Creating & Switching Branches
Work on features and fixes without disturbing the main codebase
git branch
▼
List & manage branches
See all branches or create/delete them
A branch is a separate, parallel version of your project. You create a branch to work on something new without risking the stable main code. When your work is done and tested, you merge it back in.
Think of the main branch as the live product, and a feature branch as a lab bench where you experiment freely. You only move experiments to the live shelf once they're proven to work.
# List all local branches (* marks your current branch)
$ git branch
* main
feature/login-page
# List all branches including remote ones
$ git branch -a
# Delete a branch (won't delete unmerged work)
$ git branch -d feature/login-page
git switch
▼
Create & switch branches
Move between branches or start a new one
git switch moves you to a different branch. Add -c to create a new branch at the same time. Your files instantly reflect that branch's state.
# Switch to an existing branch
$ git switch main
# Create a new branch and switch to it immediately
$ git switch -c feature/dark-mode
# The older equivalent (still works everywhere)
$ git checkout -b feature/dark-modeReal-world branch naming
1
feature/user-avatars new functionality
2
fix/broken-login-redirect bug fix
3
chore/update-dependencies maintenance task
Always commit or stash your changes before switching branches. Switching with unsaved changes can mix up work between branches.
Merging
Bring branch work back into the main codebase
git merge
▼
Combine branch changes
Fold a feature branch into main
git merge takes all the commits from one branch and applies them to the branch you're currently on. You typically switch to main first, then merge your feature branch in.
Like weaving two threads back into one fabric. The feature branch work is woven back into the main timeline, and both histories are preserved.
# 1. Switch to the branch you want to merge INTO
$ git switch main
# 2. Pull the latest main from GitHub first (good habit)
$ git pull
# 3. Merge your feature branch in
$ git merge feature/dark-mode
Merge conflicts happen when two branches edited the same lines differently. Git will pause and mark the conflicting spots in your files. Open them, choose which version to keep, delete the conflict markers, then run
git add . and git commit to finish.
Push, Pull & Fetch
Sync your local work with GitHub
git remote
▼
Manage remote connections
Link your local repo to a GitHub repository
A "remote" is a nickname for a URL. It can be your GitHub repository. When you
git clone, Git automatically creates a remote called origin pointing back to where you cloned from. You can add more remotes if needed.
# See all configured remotes
$ git remote -v
origin https://github.com/you/repo.git (fetch)
origin https://github.com/you/repo.git (push)
# Connect a local repo to GitHub for the first time
$ git remote add origin https://github.com/you/repo.git
# Add the original repo as upstream (useful for forks)
$ git remote add upstream https://github.com/original/repo.git
git push
▼
Upload commits to GitHub
Share your local commits with the world
git push uploads your local commits to your remote repository on GitHub. Until you push, your work exists only on your machine. No one else can see it.
Committing is like saving a document to your hard drive. Pushing moves it from your computer to a shared server where others can access it.
# Push the current branch to origin
$ git push
# First time pushing a new branch, set the upstream tracking
$ git push -u origin feature/dark-mode
# After that, a plain push works for that branch
$ git push
If Git says your push was rejected, it usually means someone else pushed first. Run
git pull to grab their changes, then push again.
git pull
▼
Download & merge updates from GitHub
Get everyone else's latest changes
git pull fetches the latest commits from GitHub and immediately merges them into your current branch. It's the command you run at the start of every working session to make sure you're up to date.
Imagine a shared Google Doc.
git pull is like refreshing the doc so you see all the edits your teammates made since you last looked.
# Pull updates for your current branch
$ git pull
# Pull from a specific remote and branch
$ git pull origin main
Make
git pull the first thing you do when you sit down to code on a shared project. Working from stale code is the #1 cause of merge conflicts.
git fetch
▼
Download updates without merging
Peek at remote changes before applying them
git fetch downloads new data from GitHub but doesn't change any of your local files. It updates Git's knowledge of what's on the remote without touching your working code. Great for reviewing changes before deciding to merge them.
# Fetch all updates from origin (won't change your files)
$ git fetch
# Then inspect what changed before merging
$ git log --oneline HEAD..origin/main
# Now merge if you're happy
$ git merge origin/mainPull Requests & Forks
The GitHub collaboration workflow every contributor needs
Fork + PR
▼
The open-source contribution workflow
How to contribute to a project you don't own
A Fork is your personal copy of someone else's repository on GitHub. You make changes in your fork, then submit a Pull Request (PR), a formal proposal asking the original project to incorporate your changes.
A fork is like photocopying a library book to mark it up. A pull request is like submitting your annotated copy to the author and saying "here are improvements. Want to add these to the next edition?"
# Step 1: Fork on GitHub (click the Fork button on the repo page)
# Step 2: Clone YOUR fork locally
$ git clone https://github.com/YOUR-NAME/repo.git
# Step 3: Add the original repo as "upstream"
$ git remote add upstream https://github.com/ORIGINAL/repo.git
# Step 4: Create a branch for your changes
$ git switch -c fix/typo-in-readme
# Step 5: Make changes, stage, and commit
$ git add .
$ git commit -m "Fix typo in README introduction"
# Step 6: Push your branch to YOUR fork
$ git push -u origin fix/typo-in-readme
# Step 7: Open GitHub and click "Compare & pull request"
Keep your fork's
main branch in sync with the original: git fetch upstream then git merge upstream/main. This avoids messy conflicts when you start new contributions.
git tag
▼
Mark a release version
Pin a commit as a named milestone like v1.0.0
Tags are permanent labels you attach to specific commits, most often to mark software releases. Unlike branches, tags don't move.
v1.0.0 always points to the same commit forever.
# Create an annotated tag (recommended for releases)
$ git tag -a v1.0.0 -m "First stable release"
# List all tags
$ git tag
# Push tags to GitHub (they don't push automatically)
$ git push --tagsUndo & Stash
Git never loses your work — here's how to get it back
git stash
▼
Temporarily shelve your changes
Save half-finished work so you can switch context
git stash takes your uncommitted changes, tucks them into a hidden stack, and restores your files to the last clean commit. You can pop the changes back out any time. Perfect for "I need to drop everything and fix an urgent bug right now."
Like clicking "Save Draft" on an email you're not ready to send. Your half-written work is preserved so you can come back to it exactly where you left off.
# Stash all current changes
$ git stash
# Give your stash a descriptive name
$ git stash push -m "WIP: half-finished nav redesign"
# List everything in your stash stack
$ git stash list
stash@{0}: WIP: half-finished nav redesign
# Restore the most recent stash
$ git stash pop
git restore
▼
Discard changes to a file
Roll a file back to its last committed state
Made a mess of a file and just want to start over?
git restore throws away your uncommitted changes to a specific file and brings it back to exactly how it was at the last commit.
# Discard changes to one file (⚠️ permanent! They're gone)
$ git restore index.html
# Remove a file from staging (un-add it)
$ git restore --staged index.html
# Discard all uncommitted changes in the whole project
$ git restore .git restore on unstaged files is permanent. The changes are gone, not in a recycle bin. Use it only when you're sure you want to throw the work away.
git revert
▼
Undo a commit safely
Create a new commit that cancels an old one, history intact
git revert is the safe, collaborative way to undo a commit that's already been pushed. It creates a brand-new commit that is the exact opposite of the bad commit, leaving the full history intact so teammates aren't confused.
It's like writing a correction notice in a published newspaper. You don't tear out the original page. You add a new page saying "ignore that, here's what's correct."
# Find the commit hash you want to undo
$ git log --oneline
a3f21bc Add broken feature <-- this one
7c4d9a1 Add contact page
# Revert it (creates a new "undo" commit)
$ git revert a3f21bc
# Push the revert commit to GitHub
$ git push
Always prefer
git revert over git reset for commits that have already been pushed. Resetting shared history confuses everyone else working on the repo.
git reset
▼
Move HEAD backward in history
Undo local commits before pushing. Handle with care
git reset moves the current branch pointer back to an earlier commit. Use --soft to keep your changed files, or --hard to completely wipe them. Only use this on commits you haven't pushed yet.
# Undo last commit but KEEP all the file changes staged
$ git reset --soft HEAD~1
# Undo last commit and unstage changes (files still modified)
$ git reset --mixed HEAD~1
# Undo last commit and DESTROY all changes (⚠️ permanent)
$ git reset --hard HEAD~1
Never use
git reset --hard on commits that have been pushed to GitHub. It rewrites history and will cause serious problems for anyone else working from that branch.
Quick Reference Cheat Sheet
The commands you'll use every single day
git status
What changed? Am I staged?
git add .
Stage all changes
git commit -m "msg"
Save staged snapshot
git push
Upload commits to GitHub
git pull
Download + merge latest
git clone <url>
Copy a repo locally
git switch -c <name>
Create + switch branch
git merge <branch>
Merge branch into current
git log --oneline
Compact commit history
git diff
See unstaged changes
git stash
Shelve current work
git stash pop
Restore shelved work
git revert <hash>
Safely undo a commit
git restore <file>
Discard file changes
git fetch
Download without merging
git branch -a
List all branches