Git CLI Crash Course: From Zero to Version Control Hero
Learn Git the practical way. No fluff, just the commands you'll actually use every day, plus the ones that'll save you when things go wrong.
Git CLI Crash Course: From Zero to Hero 🚀
Alright, let's be honest. Git can feel intimidating. All those commands, the weird terminology, the fear of somehow deleting everything. I've been there.
But here's what I've learned after years of using Git daily: you really only need to know about 20 commands for 95% of your work. The rest you can look up when you need them.
So let's skip the theory-heavy explanations and get you productive with Git as fast as possible.
📋 What We're Covering
- Git Fundamentals
- Commands You'll Use Every Day
- Branching and Merging
- Working with Others
- Fixing Your Mistakes
- Power User Stuff
- Good Habits
- Common Mistakes
🎯 Git Fundamentals
What Even Is Git?
Git tracks changes in your code. That's it. Every time you save a "checkpoint" (called a commit), Git remembers exactly what your code looked like at that moment.
The magic is that unlike something like Google Docs, everyone on the team has their own complete copy of the project history. You can work offline, and nothing is lost if one person's computer dies.
The Three Places Your Files Live
This trips people up, so let me break it down simply:
Working Directory → Staging Area → Repository
(your files) (ready to save) (saved history)
Or think of it like this:
Edit files → git add → git commit → git push
📝 ➕ 💾 ☁️
First Time Setup
Before you can do anything, Git needs to know who you are:
# Tell Git your name and email
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
# Use 'main' as default branch (the new standard)
git config --global init.defaultBranch main
# Set your editor for commit messages
git config --global core.editor "code --wait" # VS Code
# OR
git config --global core.editor "vim"
# See what you've set
git config --list
Do this once and you're done forever.
💼 Commands You'll Use Every Day
Starting Out
# Start a new project
git init
git init my-project # Creates folder and initializes
# Get someone else's project
git clone https://github.com/user/repo.git
git clone https://github.com/user/repo.git my-folder # Different folder name
The Workflow You'll Repeat a Thousand Times
# 1. Check what's changed (seriously, run this constantly)
git status
# 2. Stage what you want to save
git add file.txt # One file
git add folder/ # Whole folder
git add . # Everything
git add *.js # All JS files
git add -p # Review each change (super useful)
# 3. Save your changes
git commit -m "Add user authentication"
git commit -am "Quick commit" # Stage + commit tracked files
git commit --amend # Oops, fix that last commit message
# 4. See what happened
git log # Full history
git log --oneline # Compact (my favorite)
git log --graph --all --decorate # Pretty branch visualization
git log -5 # Just last 5
git log --since="2 weeks ago" # Recent stuff
# 5. See what changed
git diff # What's different (unstaged)
git diff --staged # What's staged
git diff HEAD # Everything since last commit
git diff branch1 branch2 # Compare branches
The git status and git log --oneline commands are your best friends. When in doubt, run them.
🌳 Branching and Merging
Branches are probably Git's best feature. You can try out ideas without messing up the stable code.
Branch Basics
# Create a new branch
git branch feature-login
git branch feature-login main # Branch from specific point
# Switch to it
git checkout feature-login
git switch feature-login # Newer, cleaner way
# Create and switch in one go (what you'll usually do)
git checkout -b feature-login
git switch -c feature-login # Newer version
# See your branches
git branch # Local ones
git branch -r # Remote ones
git branch -a # All of them
git branch -v # With last commit info
# Rename
git branch -m old-name new-name
git branch -M new-name # Rename the one you're on
# Delete
git branch -d feature-login # Safe delete (won't delete unmerged)
git branch -D feature-login # Force delete (careful!)
Merging Branches Together
# Go to the branch you want to merge INTO
git checkout main
# Merge the other branch in
git merge feature-login
# Some useful options
git merge --no-ff feature-login # Always create a merge commit
git merge --squash feature-login # Combine all commits into one
# Things got messy? Back out
git merge --abort
Dealing with Merge Conflicts
Sometimes Git can't figure out how to combine changes. When that happens, you'll see something like this in your file:
======= HEAD
Your changes
=======
Their changes
======= branch-name
Don't panic. Here's what to do:
# 1. Open the file and pick what you want to keep
# 2. Delete the ======= and branch markers
# 3. Stage the fixed file
git add conflicted-file.txt
# 4. Finish the merge
git commit
Want something visual? Run git mergetool to use a GUI merger.
🤝 Working with Others
Managing Remotes
# Connect to GitHub (or wherever)
git remote add origin https://github.com/user/repo.git
# See what's connected
git remote -v
# Change the URL
git remote set-url origin https://new-url.git
# Remove a connection
git remote remove origin
Push and Pull
# Send your stuff
git push origin main
git push -u origin main # Set it as default upstream
git push --all # All branches
git push --tags # All tags
# Get their stuff
git pull origin main # Download and merge
git pull --rebase origin main # Download and rebase (cleaner)
# Just download without merging (safer)
git fetch origin
git fetch --all # From all remotes
Typical Workflow When Collaborating
Here's basically what I do every day:
# 1. Start fresh
git checkout -b feature-new-ui
# 2. Do work, commit as you go
git add .
git commit -m "Add new UI components"
# 3. Push it up
git push -u origin feature-new-ui
# 4. Keep your branch up to date with main
git checkout feature-new-ui
git fetch origin main
git merge origin/main
⏮️ Fixing Your Mistakes
This is where Git really shines. Almost nothing is permanent.
"I didn't mean to stage that"
# Unstage but keep changes
git restore --staged file.txt # Modern way
git reset HEAD file.txt # Old way
# Throw away changes entirely (careful!)
git restore file.txt # Modern (⚠️ DESTRUCTIVE)
git checkout -- file.txt # Old way (⚠️ DESTRUCTIVE)
# Nuclear option - discard EVERYTHING
git restore . # ⚠️ DANGER
git reset --hard HEAD # ⚠️ DANGER
"I messed up that commit"
# Undo commit but keep changes staged
git reset --soft HEAD~1
# Undo commit, keep changes unstaged
git reset HEAD~1
git reset --mixed HEAD~1 # Same thing
# Undo commit AND throw away changes
git reset --hard HEAD~1 # ⚠️ DESTRUCTIVE
# Undo multiple commits
git reset --soft HEAD~3 # Last 3
# Make a new commit that reverses an old one (safe for shared code)
git revert abc123
git revert HEAD # Revert last commit
"I already pushed it..."
# Don't reset pushed commits! Use revert instead:
git revert abc123
git push origin main
# If you REALLY have to force push:
git push --force-with-lease origin main # At least this checks first
Never force push to a shared branch like main. You'll mess up everyone else.
🔥 Power User Stuff
Stashing (Pause Your Work)
Need to switch branches but you're mid-work? Stash it.
# Stash current changes
git stash
git stash save "Work on login feature"
# See your stashes
git stash list
# Get them back
git stash apply # Keep in stash list
git stash pop # Remove from stash list
# For a specific stash: git stash pop stash@[N]
# See what's in a stash
git stash show
git stash show -p # Full diff
# Clean up
# Delete one: git stash drop stash@[N]
git stash clear # Delete all
Cherry-Picking
Grab specific commits from other branches:
# Apply one commit to current branch
git cherry-pick abc123
# Multiple commits
git cherry-pick abc123 def456
# Apply without committing (lets you modify first)
git cherry-pick --no-commit abc123
Interactive Rebase
Rewrite history. Incredibly powerful, slightly dangerous.
# Edit last 3 commits
git rebase -i HEAD~3
In the editor, you can:
pick= keep as isreword= change commit messageedit= stop and let you amendsquash= combine with previousfixup= combine, throw away messagedrop= delete entirely
Example:
pick abc123 Add feature
squash def456 Fix typo
reword ghi789 Update docs
Reflog - Your Safety Net
Even if you "delete" something, Git usually remembers for 30 days.
# See everything that's happened
git reflog
# Found what you lost? Get it back
git checkout abc123 # Just look at it
git cherry-pick abc123 # Grab just that commit
git reset --hard abc123 # Reset to that point
Reflog has saved me more times than I can count.
Tags
Mark important points like releases:
# Lightweight tag
git tag v1.0.0
# Annotated tag (better for releases)
git tag -a v1.0.0 -m "Release version 1.0.0"
# List them
git tag
git tag -l "v1.*" # Pattern match
# Push tags
git push origin v1.0.0
git push origin --tags
# Delete
git tag -d v1.0.0
git push origin :refs/tags/v1.0.0 # Delete from remote
✅ Good Habits
Write Good Commit Messages
Use Conventional Commits format:
type(scope): subject
body
footer
Types you'll use:
feat: New featurefix: Bug fixdocs: Documentationstyle: Formatting onlyrefactor: Code change that isn't a fix or featuretest: Adding testschore: Maintenance
Examples:
git commit -m "feat(auth): add password reset functionality"
git commit -m "fix(api): handle null response in user endpoint"
git commit -m "docs(readme): update installation instructions"
Branching Strategy
Keep it simple:
main ──●────●────●────●── (production)
/ \
develop ───●────●───●──────●── (integration)
/ / \
feature-x ─●────● \
\ \
feature-y ●────●───●
Name branches clearly:
feature/user-authentication
bugfix/login-error
hotfix/critical-security-patch
release/v1.2.0
One Commit = One Change
# ❌ Don't do this
git commit -m "Fix login, update styles, add tests, refactor utils"
# ✅ Do this instead
git commit -m "fix(auth): resolve token expiration issue"
git commit -m "style(login): update button colors to match design"
git commit -m "test(auth): add unit tests for login flow"
git commit -m "refactor(utils): extract date formatting to helper"
Always Pull First
git pull --rebase origin main
git push origin main
Use .gitignore
touch .gitignore
Common patterns:
# Dependencies
node_modules/
vendor/
# Environment
.env
.env.local
# Build output
dist/
build/
out/
# IDE stuff
.vscode/
.idea/
*.swp
# OS junk
.DS_Store
Thumbs.db
# Logs
*.log
npm-debug.log*
⚠️ Common Mistakes
Working Too Long Without Committing
I've seen people code for 8 hours straight then make one giant commit. Don't do this. Commit every time you finish something logical.
git add .
git commit -m "Implement user login validation"
Committing to the Wrong Branch
We've all done it. Here's the fix:
git reset --soft HEAD~1 # Undo the commit
git stash # Save the changes
git checkout -b correct-branch # Make the right branch
git stash pop # Get changes back
git commit -m "Add feature" # Commit on correct branch
Forgetting to Pull
Always start your day with:
git pull origin main
git checkout -b new-feature
Force Pushing to Shared Branches
# ❌ NEVER do this on main
git push --force origin main
# ✅ If you must force push, use this (at least it checks)
git push --force-with-lease origin feature-branch
Committing Large Files
Git doesn't handle big files well. If you've already committed one:
- Use BFG Repo-Cleaner to remove it from history
- Set up Git LFS going forward
git lfs track "*.psd"
git lfs track "*.mp4"
🎓 Quick Cheat Sheet
Setup
git config --global user.name "Name"
git config --global user.email "email"
git init
git clone [url]
Daily Workflow
git status
git add [file]
git commit -m "message"
git push
git pull
Branching
git branch [name]
git checkout [name]
git checkout -b [name]
git merge [branch]
git branch -d [name]
Looking at History
git log
git log --oneline
git diff
git show [commit]
Undoing Things
git restore [file]
git reset HEAD~1
git revert [commit]
git stash
Remotes
git remote add origin [url]
git push origin [branch]
git pull origin [branch]
git fetch
🚀 What's Next?
You've got the fundamentals. Here's how to keep leveling up:
- Just use it. Use Git for everything, even tiny projects
- Read commit history on open source projects. See how pros do it
- Try the advanced stuff when you're comfortable. Hooks, submodules, worktrees
- Pick a workflow. GitFlow, GitHub Flow, or trunk-based development
- Get good at rebasing.
git rebase -iis powerful once you get it
Good Resources
- Pro Git Book - Free and thorough
- Oh Shit, Git!?! - When you've messed up
- Learn Git Branching - Interactive practice
- Git Explorer - Find commands by what you want to do
💡 Things to Remember
- Commit often, push reasonably
- Read error messages. Git actually tells you what went wrong
- Don't panic. Reflog remembers almost everything
- Branches are free. Use them liberally
- Pull before you push
Now go build something! 🎉
Questions? Find me on X/Twitter.
