❓ Why Every Developer Needs Git
⏰
Time Machine
Go back to any point in your project's history. Broke something? Reset to yesterday's working code in one command.
🤔
Safe Experimentation
Create a branch to try a risky idea. If it works, merge it. If it fails, delete it. Your main code stays safe.
👥
Team Superpower
100 developers editing the same codebase simultaneously — zero conflicts. Git tracks who changed what, when, and why.
⚙ One-Time Setup — Do This Before Anything Else
terminal — one-time configuration
# Tell Git who you are (required for every commit)
$ git config --global user.name "Your Name"
$ git config --global user.email "you@example.com"
# Set VS Code as your default editor
$ git config --global core.editor "code --wait"
# Set default branch name to "main"
$ git config --global init.defaultBranch main
# Verify your settings
$ git config --list
user.name=Your Name
user.email=you@example.com
✔ Setup complete!
💡
--global means this setting applies to all your projects on this machine. Without it, the setting only applies to the current repository.
👤
Your name and email appear in every commit message. Use the same email as your GitHub account so commits link to your profile.
⚠
Windows users: Also run git config --global core.autocrlf true to handle line-ending differences between Windows and Linux/Mac.
🔄 The 4 Zones — How Git Thinks About Your Files
📁
Working Directory
Your actual files on disk. Where you write & edit code.
Your laptop
📜
Staging Area
A "draft" of your next commit. You choose which changes go in.
Index / Cache
🌳
Local Repository
All commits saved permanently in the hidden .git folder.
.git/objects
☁️
Remote (GitHub)
A copy of your repository on GitHub, shared with your team.
github.com/you/repo
🠖 git add <file>
🠘 git restore <file>
🠖 git commit -m "msg"
🠘 git reset HEAD~1
🠖 git push origin main
🠘 git pull / git fetch
💡
Key Insight: You control exactly what goes into each commit via the staging area. You can edit 5 files but only commit 2 of them — stage only those 2 with git add. This is how professionals write clean, focused commit histories.
📄 The 12 Commands You'll Use Every Single Day
git initSetup
Start tracking a new project with Git
Creates a hidden .git folder that stores your entire version history. Run once per project.
$ git init # in your project folder
Initialized empty Git repository in .git/
git clone <url>Setup
Copy an existing repo from GitHub to your machine
Downloads all files, all history, and sets up a remote connection to GitHub automatically.
$ git clone https://github.com/you/project.git
# creates a folder named "project"
git statusInspect
"What has changed?" — your most-used command
Shows modified files (red = unstaged, green = staged) and untracked new files. Run this constantly.
$ git status
modified: src/app.py
new file: README.md
git log --onelineInspect
See the project's commit history
Each line = one commit. The 7-char code (hash) is its unique ID. Use this to find where to roll back.
$ git log --oneline
a1b2c3d feat: add login endpoint
e4f5g6h fix: correct email validation
git add <file>Stage
Move a file's changes to the staging area
Use git add . to stage everything, or name specific files for a cleaner commit.
$ git add src/app.py # one file
$ git add . # everything changed
git commit -m "msg"Save
Permanently save a snapshot of staged changes
The message should complete: "This commit will..." — use present tense. E.g., "add user login" not "added".
$ git commit -m "feat: add JWT auth endpoint"
git pushRemote
Send your local commits to GitHub
First time pushing a new branch, use -u to link local branch to remote.
$ git push # after first time
$ git push -u origin feature/login # first time
git pullRemote
Download latest changes from GitHub to your machine
Does git fetch + git merge in one step. Always pull before you start coding.
$ git pull origin main # get latest from main
git checkout -bBranch
Create a new branch and switch to it immediately
Never code directly on main. Always branch for every feature or bugfix.
$ git checkout -b feature/user-login
Switched to a new branch 'feature/user-login'
git merge <branch>Branch
Combine another branch's commits into the current branch
Switch to main first, then merge your feature branch into it.
$ git checkout main
$ git merge feature/user-login
git diffInspect
See exactly what lines changed in your files
Red lines (-) were removed, green lines (+) were added. Use before every commit.
$ git diff # unstaged changes
$ git diff --staged # staged changes
git stashEscape Hatch
Temporarily shelve uncommitted work to switch tasks
Boss says "urgent bug on main NOW" — stash your work, fix the bug, then git stash pop to restore.
$ git stash # save & clean working dir
$ git stash pop # restore your work
🌸 Branching — Your Most Powerful Workflow Tool
main A ──── B ──────────────── E ── F
\ /
feat C ── D ── (work) ── D'
💡
Rule: main = always working code that could go to production. Every new feature or bugfix gets its own branch. When done, merge back and delete the branch.
# 1. See all branches
$ git branch
* main
# 2. Create + switch to new branch
$ git checkout -b feature/login
Switched to a new branch 'feature/login'
# 3. Do work... commit...
$ git add . && git commit -m "feat: login"
# 4. Push branch to GitHub
$ git push -u origin feature/login
# 5. After PR is merged — clean up
$ git checkout main
$ git pull
$ git branch -d feature/login
🌟 Real Scenario — Build & Ship a Feature Like a Professional
📞 Scenario: You've been asked to add a "forgot password" feature to the app
1
Get the latest code
git checkout main && git pull origin main
Always start from the most up-to-date main. Never branch off stale code.
2
Create a feature branch
git checkout -b feature/forgot-password
Name it clearly. Your team should know what the branch does just by reading the name.
3
Write your code
code . # open VS Code
Edit files, write tests, implement the feature. Normal coding work.
4
Check what you changed
git status git diff
Always review your changes before staging. Never commit blindly.
5
Stage specific files
git add src/auth.py tests/test_auth.py
Stage only related files. Don't commit unrelated debug prints.
6
Write a good commit message
git commit -m "feat: add forgot password email flow"
Use conventional commits: feat: fix: docs: test: refactor:
7
Push your branch
git push -u origin feature/forgot-password
This creates the branch on GitHub. Only needed with -u the first time.
8
Open a Pull Request on GitHub
gh pr create --title "feat: forgot password"
Your team reviews the code, suggests changes, approves, then merges. You're done!
🔄 Undo Mistakes — "I Accidentally..." Scenarios
| Situation |
Command to Fix It |
Safe? |
What It Does |
| I edited a file but want the original back |
git restore <file> |
✓ Safe |
Discards unstaged changes in a file. Gets the last committed version. |
I staged a file with git add but don't want it in this commit |
git restore --staged <file> |
✓ Safe |
Moves the file back from staging to working directory. Your edits stay. |
| I committed but want to edit the message or add a missed file |
git commit --amend |
⚠ Local only |
Replaces the last commit. Only use if you haven't pushed yet. |
| I committed the wrong thing — want to undo but keep my code |
git reset --soft HEAD~1 |
✓ Safe |
Un-commits the last commit. Your changes stay staged, ready to recommit. |
| I need to undo a commit that's already been pushed (shared) |
git revert <commit-hash> |
✓ Safe |
Creates a NEW commit that undoes the changes. Safe for shared/public repos. |
| I need to completely wipe all uncommitted changes right now |
git reset --hard HEAD |
⛔ Destructive |
Permanently discards all uncommitted changes. Cannot be undone. Use carefully. |
| I committed a secret key or password by mistake |
Use BFG Repo Cleaner + rotate the key immediately |
⛔ Complex |
Treat the secret as compromised. Rotate it first, then scrub history. Never just delete the commit — the hash is still in history. |
| I deleted a file and want it back |
git checkout HEAD -- <file> |
✓ Safe |
Restores the file from the last commit, even if you've deleted it from disk. |
| I want to go back to a specific old commit temporarily |
git checkout <commit-hash> |
⚠ Detached HEAD |
Puts you in "detached HEAD" mode — you can look around but don't commit here. Use git checkout main to get back. |
👥 Team Workflow — From Fork to Merged PR
🍴
Fork / Clone
Copy repo to your account & machine
🌳
Branch
checkout -b feature/xxx
💻
Code
Write & test locally
📥
Commit
git add + git commit
🚀
Push
git push -u origin branch
👥
PR Review
Team reviews, comments, approves
✔
Merged!
Code goes to main & deploys
⚡ Resolving Merge Conflicts
conflict markers in your file
<<<<<<< HEAD
def greet(): return "Hello" # your version
=======
def greet(): return "Hi there" # teammate's version
>>>>>>> feature/greeting
# Edit the file: keep what you want,
# delete the conflict markers, then:
$ git add src/app.py
$ git commit -m "merge: resolve greeting conflict"
📑 Conventional Commit Messages
| Prefix | When to Use | Example |
| feat: | New feature | feat: add login API |
| fix: | Bug fix | fix: correct null check |
| docs: | Documentation only | docs: update README |
| test: | Adding/fixing tests | test: cover edge cases |
| refactor: | Code cleanup, no feature change | refactor: extract helper |
| chore: | Build/config changes | chore: update deps |
🕷 .gitignore — Never Commit Secrets or Junk Files
⚠
Important: Create a .gitignore file in your project root before your first commit. Once a file is tracked by Git, adding it to .gitignore later won't stop tracking — you'd need git rm --cached <file> first.
☕ Java / Spring Boot
# Build output
target/
*.class
*.jar
# IDE files
.idea/
*.iml
# Secrets
application-secret.properties
.env
🐍 Python / Django
# Virtual environment
venv/
__pycache__/
*.pyc
# Django
*.sqlite3
media/
# Secrets
.env
local_settings.py
🌐 Node / React
# Dependencies
node_modules/
# Build output
dist/
build/
.next/
# Secrets
.env
.env.local
✍ Complete Cheat Sheet — Quick Reference
📄 Setup & Info
- git initStart tracking current folder
- git clone <url>Copy repo from GitHub
- git statusShow changed/staged files
- git log --onelineCompact commit history
- git diffLine-by-line changes (unstaged)
- git diff --stagedLine-by-line changes (staged)
- git show <hash>Inspect a specific commit
📥 Staging & Committing
- git add <file>Stage one file
- git add .Stage all changed files
- git add -pStage changes interactively (hunks)
- git commit -m "msg"Save staged snapshot
- git commit --amendEdit last commit (before push)
- git stashShelve uncommitted work
- git stash popRestore shelved work
🌸 Branches
- git branchList all local branches
- git branch -aList local + remote branches
- git checkout -b <name>Create + switch to branch
- git checkout <name>Switch to existing branch
- git merge <branch>Merge branch into current
- git branch -d <name>Delete merged branch
- git rebase mainReapply commits on top of main
🔄 Undo
- git restore <file>Discard unstaged changes
- git restore --staged <file>Unstage a file
- git reset --soft HEAD~1Undo commit, keep staged
- git reset --hard HEAD~1Undo commit & discard changes
- git revert <hash>Safe undo (new commit)
- git clean -fdDelete untracked files/dirs
☁️ Remote / GitHub
- git remote -vShow remote connections
- git fetch originDownload changes (don't merge)
- git pull origin mainDownload + merge latest
- git push origin <branch>Upload branch to GitHub
- git push -u origin <branch>Push + set upstream (first time)
- git remote add origin <url>Connect local repo to GitHub
✍ Power Tools
- git log --graphVisual branch history
- git blame <file>Who changed which line?
- git bisectBinary search for a bug commit
- git cherry-pick <hash>Apply one commit from another branch
- git tag v1.0.0Mark a release point
- git shortlog -snCommit count per contributor
⚡ Pro Tips — What Separates Junior from Senior
💨
Commit early, commit often
Small commits are easier to review, revert, and understand. A commit every 30 minutes is better than one giant commit at end of day. Think of commits like Ctrl+S — do it constantly.
📄
Write commits for your future self
"Fixed bug" is useless. "fix: prevent crash when user email is null on login" is a gift. Someone (maybe you in 6 months) will read your commit history to understand why code was written.
🕷
Set up useful Git aliases
Add to ~/.gitconfig: git config --global alias.st status, alias.lg "log --oneline --graph", alias.co checkout. Now git st = git status.
🌸
Never work directly on main
Protect your main branch. Even for solo projects. Branch → code → PR → merge. This habit scales when you join a team — you'll never accidentally push broken code to production.
👀
Review before you stage
Run git diff before git add every time. This is when you catch debug prints, commented-out code, and accidental .env files. Be intentional about every line you commit.
🚀
git pull before you push
If a teammate pushed while you were coding, your push will be rejected. Pull first to get their changes, resolve any conflicts locally, then push. This is the daily rhythm of team development.
🌳
The Golden Rule of Git
Never rewrite history that has been pushed and shared with others.
Use git revert instead of git reset --hard on shared branches. Amend, rebase, and force-push only on your own private branches.