Git & GitHub Guide

A complete beginner-friendly walkthrough — from your first commit to collaborating on GitHub. Each section builds on the previous one. Every code block has a Copy button.

Copy button on each code block  ·  ● Beginner ● Intermediate ● Advanced

01 Introduction — What are Git & GitHub?

Git is a tool that tracks changes to your files over time — like a "save history" for your entire project. Every time you decide to save a checkpoint, Git takes a snapshot of your files. You can go back to any snapshot later, compare versions, and work on multiple experiments at once without risk.

GitHub is a website that hosts Git repositories online. It lets you:

Your Computer
Git (local repo)
⟶
GitHub
Remote backup
⟶
Team
Collaboration
Analogy: Git is like a time machine for your project. GitHub is like Google Drive for that time machine — it stores your project online and lets others contribute.

02 Installation & First-Time Setup

Install Git

Configure your identity

These details are attached to every commit you make — like a signature.

# Check version
git --version

# Set your name & email (use the one on GitHub)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Recommended settings

git config --global init.defaultBranch main
git config --global color.ui auto
git config --global core.editor "code --wait"
▸ Try it yourself

Run git config --list to see all your settings. Make sure your name and email are correct — they appear in every commit!

SSH key (for GitHub): Generate one with ssh-keygen -t ed25519 -C "you@example.com" then add the public key at GitHub → Settings → SSH and GPG keys. This lets you push without typing a password every time.

03 Your First Repository

A repository (or "repo") is a folder that Git is watching. There are two ways to start:

▶git init Create a new repo from scratch
mkdir my-project
cd my-project
git init

This creates a hidden .git folder inside your project. Now Git is tracking everything in this directory. Run ls -la to see the .git folder — that's Git's "brain". Don't touch it manually!

▶git clone Copy an existing repo from GitHub
git clone https://github.com/user/repo.git
# or with SSH (no password each time):
git clone git@github.com:user/repo.git

This downloads the entire project history to your computer. You get everything — all files, all branches, all commits.

▶git status Check what's happening
git status

This is the most-used Git command. It tells you which files are modified but not staged, which files are staged ready to commit, and which files are untracked (new files Git doesn't know about).

▸ Your first Git exercise

mkdir test && cd test && git init — then create a file hello.txt, write something in it, and run git status. You'll see it as "Untracked".

04 The Daily Workflow Beginner

Git has three areas where your files live. Understanding these is the key to everything else:

Working Directory
You edit files here
⟶ git add
Staging Area
Prepare your snapshot
⟶ git commit
Repository
Saved permanently

The daily cycle is always: Edit → Add → Commit

▶git add Stage changes
git add filename.txt       # stage one specific file
git add .                  # stage ALL changes
git add -p                 # stage interactively — pick what to include

Staging is like picking which items to put in a photo before taking the picture. You don't have to commit everything.

▶git commit Take a snapshot
git commit -m "Add login button"
git commit -am "Fix typo"   # shortcut: add + commit (tracked files only)

Every commit has a message describing what changed. Write clear messages so your future self (and others) understand why.

Golden rule: Commit early and often. A commit is a safe checkpoint — you can always go back. Think of it like saving in a video game.

Good commit messages

# Use imperative mood (like giving a command):
git commit -m "Add user authentication"
git commit -m "Fix crash when file is missing"
git commit -m "Update dependencies"

05 Exploring History Beginner

Once you have commits, you can explore your project's timeline.

▶git log View commit history
git log                      # full history
git log --oneline            # compact (one line per commit)
git log --oneline --graph    # show branch structure visually
git log --oneline -5         # last 5 commits only
git log --author="Laksh"   # commits by a specific person
▶git show See what a commit changed
git show HEAD                # show the latest commit
git show abc1234             # show a specific commit (use its hash)
git show HEAD~2              # show what changed 2 commits ago
▶git diff Compare changes
git diff                     # unstaged changes (working dir vs staging)
git diff --staged            # staged changes (vs last commit)
git diff HEAD~1..HEAD        # changes between two commits
git diff branch-a..branch-b  # compare two branches
▶git shortlog Summarized log (grouped by author)
git shortlog                 # shows commits grouped by author
git shortlog -sn             # same but with commit count only
▶git blame See who changed each line
git blame README.md          # shows who last touched each line
git blame -L 10,20 src/app.js  # lines 10-20 only

Useful when you find a bug and want to ask "who wrote this line?" (including your past self).

▶git grep Search within tracked files
git grep "search-term"       # search all tracked files
git grep "TODO"              # find all TODOs in your project

Faster than regular grep because it only searches tracked files.

06 Ignoring Files Beginner

Not everything should be committed. Create a file called .gitignore in your project root to tell Git which files to skip.

# .gitignore — example for a Node.js project
node_modules/
.env
*.log
.DS_Store
dist/
coverage/
.vscode/
⚠ Important: Add .gitignore before committing sensitive files. If you accidentally commit a password, it stays in the history forever!

Need a template? github/gitignore has templates for every language.

▶git check-ignore Debug why a file is ignored
git check-ignore -v some-file.log

Shows which rule in .gitignore is ignoring that file.

07 Undoing Changes Intermediate

Mistakes are normal. Here's how to undo at every stage — from safest to most destructive.

▶git restore Discard unstaged changes (safe)
git restore filename.txt           # discard changes in working directory
git restore .                      # discard all unstaged changes
# Older syntax (still works):
git checkout -- filename.txt

⚠ This permanently discards unsaved work in that file. You cannot get it back!

▶git restore --staged Unstage a file (keep changes)
git restore --staged filename.txt   # unstage, but keep file changes
git restore --staged .              # unstage everything

Your file changes are preserved — they just move out of the staging area back to your working directory.

▶git reset Undo commits (rewrite history)
# Soft — undo commit, keep changes staged
git reset --soft HEAD~1

# Mixed (default) — undo commit, unstage changes
git reset HEAD~1

# Hard — DESTROY everything after the target commit ⚠
git reset --hard HEAD~1

HEAD~1 = "one commit before HEAD". Use HEAD~n for n commits, or a full commit hash like abc1234. --hard permanently deletes uncommitted changes and commits. Only use it on commits you haven't shared.

▶git revert Safe undo (creates a new commit)
git revert HEAD                  # create a new commit that undoes HEAD
git revert abc1234               # undo a specific commit by hash

Unlike reset, revert does not delete history. It makes a new commit that cancels out the old one. Safe to use on shared branches!

▶git clean Remove untracked files
git clean -n                  # preview what would be deleted (dry run)
git clean -f                  # delete untracked files
git clean -fd                 # delete untracked files + directories

Always run git clean -n first to see what will be removed!

08 Branching Intermediate

A branch is like an alternate timeline. You can experiment freely on a branch without affecting the main code. This is the foundation of Git collaboration.

main:    ●──●──●──────────────●
                    \          /
feature:             ●──●──●

The default branch is main. Feature branches branch off, get work done, then merge back.

▶git branch List, create, rename, delete
git branch                     # list local branches (* = current)
git branch feature-x           # create a new branch called feature-x
git branch -m old new          # rename a branch
git branch -d feature-x        # delete branch (only if merged)
git branch -D feature-x        # force delete (unmerged work!)
▶git switch Move between branches (modern way)
git switch feature-x           # switch to existing branch
git switch -c new-branch       # create AND switch to new branch
git switch -                   # switch back to previous branch
▶git branch -a See all branches (local + remote)
git branch -a                  # list all branches
git branch -r                  # remote branches only
▸ Try branching yourself

git switch -c experiment — create and switch to a new branch. Make a commit here, then git switch main. Your commit on experiment is hidden away, safe and separate.

Best practice: Never commit directly to main. Always create a branch for each feature or bug fix.

09 Merging Intermediate

Merging brings changes from one branch into another. It creates a merge commit that ties the two histories together.

▶git merge Basic merge
# First, switch to the branch you want to merge INTO
git switch main

# Then merge the feature branch into main
git merge feature-x

# Force a merge commit (even if fast-forward is possible)
git merge --no-ff feature-x

Merge conflicts

When two branches change the same line of the same file, Git doesn't know which one to keep. This is a merge conflict.

# Git tells you which files have conflicts.
# Open them — you'll see markers like:
<<<<<<< HEAD
console.log("Hello");
=======
console.log("Hi there!");
>>>>>>> feature-x

# Edit the file to keep what you want, remove the markers, then:
git add resolved-file.txt
git commit  # Git creates the merge commit automatically
Tip: Use git merge --abort to cancel a conflicted merge and go back to how things were.
⚠ Conflicts are normal! Everyone gets them. Just edit the file, remove the markers, and continue.

10 Rebasing Advanced

Rebasing rewrites history by moving your commits to sit on top of another branch. It creates a clean, linear history — unlike merge which keeps a record of every fork.

▶git rebase Basic rebase
# While on your feature branch:
git switch feature-x
git rebase main
# Now your commits sit on top of main's latest commit

Before vs After

# Merge keeps the fork visible:
main:    ●──●──●─────────●───●
                    \       /
feature:             ●──●─●

# Rebase creates a straight line:
main:    ●──●──●
                 \
feature:          ●──●──●  (now on top of main)
▶git rebase -i Interactive rebase — squash, reword, reorder
# Edit the last 3 commits before pushing:
git rebase -i HEAD~3

# Inside the editor, you can:
#   pick    — keep the commit as-is
#   reword  — change the commit message
#   squash  — combine with previous commit
#   edit    — pause to make changes
#   drop    — delete the commit

This is how you clean up messy commit history before sharing it.

⚠ CRITICAL: Never rebase commits that have been pushed to a shared branch. Rebasing rewrites history — it will cause chaos for anyone else working on that branch. Use merge for shared branches.
▶git rebase --abort Cancel a rebase
git rebase --abort   # go back to before you started rebasing

11 Cherry-Pick Intermediate

git cherry-pick lets you take a specific commit from one branch and apply it to another — without merging the whole branch.

# Apply a specific commit to your current branch
git cherry-pick abc1234

# Apply multiple commits
git cherry-pick abc1234 def5678

# Cherry-pick without making a commit right away
git cherry-pick -n abc1234

When to use it:

Analogy: Cherry-pick is like picking a single grape from a bunch — you take only what you need.

12 Tagging (Version Releases) Intermediate

Tags mark specific points in history — usually for releases like v1.0, v2.3.1. Unlike branches, tags don't move.

# Create a lightweight tag
git tag v1.0.0

# Create an annotated tag (recommended — includes metadata)
git tag -a v1.0.0 -m "Release version 1.0.0"

# List all tags
git tag

# See details of a tag
git show v1.0.0

# Push tags to GitHub
git push origin v1.0.0

# Push ALL tags
git push origin --tags

# Delete a local tag
git tag -d v1.0.0
Use annotated tags for releases: git tag -a saves the tagger name, date, and a message — much more useful than lightweight tags.

13 Remote Repositories & GitHub Intermediate

A remote is a Git repository hosted on a server — typically GitHub. You push your local commits there to back them up and share them.

Connecting your local repo to GitHub

# Create a repo on GitHub first (no README, no .gitignore)
# Then connect your local repo:
git remote add origin https://github.com/your-username/your-repo.git

# Or use SSH (no password prompts):
git remote add origin git@github.com:your-username/your-repo.git

Working with remotes

git remote -v                  # list all remotes
git remote remove origin       # remove a remote
git remote rename origin upstream
▶git push Send commits to GitHub
# First push (set upstream):
git push -u origin main

# Subsequent pushes (just):
git push

# Push a specific branch:
git push origin feature-x

# Delete a remote branch:
git push origin --delete feature-x
▶git pull Get latest changes from GitHub
git pull origin main           # fetch + merge latest changes
git pull                       # if upstream is configured

git pull is a shortcut for git fetch + git merge. It downloads changes and immediately merges them.

▶git fetch Download without merging
git fetch origin               # download changes, DON'T merge
git fetch --prune              # remove stale remote-tracking branches
git diff main origin/main      # see what changed before merging

Use fetch when you want to review changes before integrating them.

pull vs fetch: git pull = fetch + merge. Use git fetch then git diff to review, then git merge manually.

14 Collaboration on GitHub Intermediate

Pull Requests (PRs)

A Pull Request tells others: "I've made changes on a branch — please review and merge them." This is the heart of GitHub collaboration.

The PR workflow:

  1. Create a branch: git switch -c fix-login-bug
  2. Make changes and commit them
  3. Push the branch: git push -u origin fix-login-bug
  4. Open a PR on GitHub from fix-login-bug → main
  5. Review & discuss: Teammates comment, suggest changes
  6. Update if needed: Push more commits — the PR updates automatically
  7. Merge once approved
  8. Clean up: Delete the remote and local branch

Forking (Open-Source Contribution)

When you don't have write access to a repo, you fork it — make a copy under your GitHub account.

# 1. Click "Fork" on GitHub
# 2. Clone YOUR fork:
git clone https://github.com/YOUR-USERNAME/repo.git

# 3. Add the original repo as "upstream":
git remote add upstream https://github.com/ORIGINAL-OWNER/repo.git

# 4. Keep your fork in sync:
git pull upstream main
git push origin main
▶git remote -v See your remotes (after forking)
origin     https://github.com/YOU/repo.git (fetch)
origin     https://github.com/YOU/repo.git (push)
upstream   https://github.com/OWNER/repo.git (fetch)
upstream   https://github.com/OWNER/repo.git (push)

origin = your fork, upstream = the original repo you forked from.

GitHub Issues

GitHub Discussions

A forum-like space for questions, ideas, and community conversations — separate from Issues (which are for actionable tasks).

PR best practices: Keep PRs small (< 300 lines). Write a clear title/description. Link to related issues. Respond to feedback quickly.

15 Stash — Save Work in Progress Intermediate

You're in the middle of work but need to switch branches? Stash shelves your changes temporarily so you can come back later.

# Save current changes (tracked files only)
git stash

# Stash with a name (organize multiple stashes)
git stash push -m "WIP: fixing login bug"

# Stash untracked files too
git stash -u

Managing stashes

git stash list            # see all saved stashes
git stash apply           # apply latest stash (keep it)
git stash pop             # apply latest stash + remove it
git stash drop            # delete latest stash
git stash clear           # delete ALL stashes
git stash show -p         # see diff of latest stash
Stash is a stack (LIFO): The most recent stash is stash@{0}, the one before is stash@{1}, etc. Use git stash pop most of the time.

16 Recovery Tools Advanced

Accidentally lost a commit? Deleted something you shouldn't have? Git has safety nets.

▶git reflog The safety net — reference log
git reflog                   # shows EVERYTHING you've done
# Output like:
# abc1234 HEAD@{0}: commit: Fix login
# def5678 HEAD@{1}: reset: moving to HEAD~1

# Recover a "lost" commit:
git reset --hard HEAD@{2}    # go back to that point

The reflog is Git's local journal of every action you've taken. Even after a git reset --hard or git rebase, you can find your old commits here. Your reflog expires after ~90 days.

▶git bisect Find the commit that introduced a bug
# Start bisecting:
git bisect start

# Mark the current commit as bad:
git bisect bad

# Mark an old commit (that you know worked) as good:
git bisect good abc1234

# Git checks out a commit halfway in between.
# Test it, then mark:
git bisect good   # if it works
git bisect bad    # if it's broken

# Git narrows it down to one commit. When done:
git bisect reset

git bisect uses binary search to find the exact commit where a bug was introduced. For 1000 commits, it takes only ~10 steps!

17 More GitHub Features

▶Actions Automate workflows (CI/CD)

GitHub Actions runs tasks automatically when events happen — like running tests on every push.

# .github/workflows/test.yml — example
name: Run tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm install
      - run: npm test

Common use cases: run tests, deploy to a server, lint code, publish packages.

▶Pages Host websites for free

GitHub Pages serves static websites directly from a repository. Great for docs, portfolios, project sites.

  • Go to repo → Settings → Pages
  • Select branch (usually main or gh-pages)
  • Your site is live at https://username.github.io/repo-name
▶Projects Kanban-style project management

GitHub Projects is a built-in project management board (like Trello) linked to issues and PRs.

  • Create columns: To Do → In Progress → Done
  • Drag issues and PRs between columns
  • Automate with Actions (e.g., move to "Done" when PR merges)
▶GitHub CLI Manage GitHub from your terminal

Install gh and never leave the terminal:

gh repo create my-repo        # create a repo on GitHub
gh pr create                  # create a pull request
gh pr checkout 42             # checkout PR #42 locally
gh issue list                 # list open issues
gh repo view                  # view repo details

Install: brew install gh (macOS), sudo apt install gh (Linux), or download from cli.github.com.

18 Advanced Topics Advanced

▶git submodule Include other repos inside your repo
# Add a submodule
git submodule add https://github.com/user/library.git lib/library

# Clone a repo WITH its submodules
git clone --recurse-submodules https://github.com/user/project.git

# Update submodules to their latest commit
git submodule update --remote

Submodules let you keep a Git repo as a dependency inside another Git repo.

▶git archive Export a snapshot (without .git)
# Create a zip of your project (no .git folder)
git archive --format=zip HEAD > project.zip

# Create a tar.gz
git archive --format=tar.gz -o project.tar.gz HEAD

Perfect for sharing a clean copy of your code — no .git history, no ignored files.

▶git worktree Work on two branches at once
# Check out a branch in a separate directory
git worktree add ../project-hotfix hotfix-branch

# List worktrees
git worktree list

# Remove a worktree when done
git worktree remove ../project-hotfix

Lets you have two different branches checked out at the same time in different folders — no stashing or switching needed.

19 Quick Command Reference

Print this section or keep it bookmarked — it covers 95% of what you'll ever need.

Getting Started

git init
Create a new repo
git clone <url>
Copy a remote repo
git status
Check file status
git config --list
View all settings

Daily Work

git add .
Stage all changes
git commit -m "msg"
Commit staged changes
git commit -am "msg"
Add + commit shortcut
git diff
Show unstaged changes

History

git log --oneline
Compact history
git log --graph
Visual branch history
git show HEAD
Latest commit details
git blame <file>
Who changed each line
git shortlog -sn
Commits per author
git grep "text"
Search tracked files

Undoing

git restore <f>
Discard unstaged changes
git restore --staged <f>
Unstage a file
git reset --soft HEAD~1
Undo commit, keep staged
git reset HEAD~1
Undo commit, unstage
git reset --hard HEAD~1
⚠ Discard commit + changes
git revert HEAD
Safe undo (new commit)
git clean -fd
Delete untracked files

Branches

git branch
List local branches
git branch <name>
Create a branch
git switch <b>
Switch branches
git switch -c <b>
Create + switch
git branch -d <b>
Delete merged branch
git merge <b>
Merge branch into current
git rebase <b>
Rebase onto branch
git cherry-pick <h>
Apply a specific commit

Remote & GitHub

git remote -v
List remotes
git push -u origin main
First push to GitHub
git push
Push commits
git pull
Fetch + merge
git fetch
Download without merge
git tag -a v1.0 -m "msg"
Create annotated tag
git push origin --tags
Push all tags

Saving & Recovery

git stash
Save work in progress
git stash pop
Apply + remove stash
git reflog
Show all actions
git bisect start
Find bug by binary search
Remember: You don't need to memorize everything. git --help or git <command> --help opens the manual for any command. Come back to this guide whenever you need.