Let me tell you about the time I accidentally deleted my entire project two days before the deadline.
It was 2 AM. I was tired. I ran git reset --hard HEAD thinking it would undo my last commit. Instead, I watched three weeks of work vanish in a second. No backup. No recovery. Just gone.
That night, I learned more about Git than I had in the entire semester.
If you're a CS student (or anyone really) who's made Git feel like a landmine field, this one's for you. Here are the mistakes I made, the panic that followed, and most importantly—how to fix them.
Mistake #1: "I Committed to the Wrong Branch"
What I did:
# I'm on main branch
git add .
git commit -m "Added new feature"
# Oh no... this was supposed to go on feature-branch
I spent 30 minutes panicking before realizing this is actually easy to fix.
The fix:
# Don't push yet! First, create the branch you meant to use
git branch feature-branch
# Reset main to before your commit (soft keeps your changes)
git reset --soft HEAD~1
# Switch to the correct branch
git checkout feature-branch
# Now commit again
git add .
git commit -m "Added new feature"
Even better - if you already pushed:
# Create the new branch from current main
git checkout -b feature-branch
# Go back to main
git checkout main
# Reset main to remote state
git reset --hard origin/main
# Push your feature branch
git checkout feature-branch
git push -u origin feature-branch
Lesson learned: Always double-check which branch you're on before committing. I now use a terminal prompt that shows my current branch in big, bold letters.
Mistake #2: "Merge Conflict Hell"
The scenario:
git pull origin main
# Terminal explodes with:
CONFLICT (content): Merge conflict in src/App.js
CONFLICT (content): Merge conflict in src/utils.js
CONFLICT (content): Merge conflict in package.json
Automatic merge failed; fix conflicts and then commit the result.
I stared at those <<<<<<<, =======, and >>>>>>> symbols for 20 minutes completely frozen.
What those symbols mean:
<<<<<<< HEAD
// Your changes
function greet() {
console.log("Hello!");
}
=======
// Their changes
function greet() {
console.log("Hi there!");
}
>>>>>>> feature-branch
The fix:
- Don't panic - conflicts are normal
- Choose which version to keep (or combine both)
-
Delete the conflict markers (
<<<<<<<,=======,>>>>>>>) - Test your code
- Commit the resolution
# After fixing conflicts manually
git add .
git commit -m "Resolved merge conflicts"
Pro tip: Use VSCode's built-in merge conflict resolver. It shows "Accept Current Change", "Accept Incoming Change", or "Accept Both Changes" buttons. Life-changing.
Lesson learned: Pull frequently to avoid massive conflicts. Small conflicts are way easier to resolve than 47 files all conflicting at once.
Mistake #3: "I Want to Undo My Last Commit"
I've made bad commits. We all have. Here's what I learned:
Scenario 1: I haven't pushed yet
# Undo commit but keep changes (most common)
git reset --soft HEAD~1
# Undo commit AND changes (dangerous!)
git reset --hard HEAD~1
# Undo last 3 commits
git reset --soft HEAD~3
Scenario 2: I already pushed to GitHub
# Create a new commit that undoes the last one
git revert HEAD
# This is safer than reset because it doesn't rewrite history
The difference:
-
resetrewrites history (dangerous if you've already pushed) -
revertcreates a new commit that undoes changes (safe for shared branches)
Lesson learned: If you've pushed, use revert. If you haven't, reset --soft is your friend.
Mistake #4: "I Accidentally Committed Sensitive Data"
The worst. I committed my .env file with API keys to a public repo. Realized it 5 minutes after pushing.
What I did (WRONG):
git rm .env
git commit -m "Remove .env"
git push
The problem: The file is still in Git history. Anyone can see it in previous commits.
The RIGHT way:
# Remove from all history (use with caution!)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# Force push (rewrites history)
git push --force
Better - use BFG Repo Cleaner (easier and faster):
# Install BFG
brew install bfg # or download from bfg.org
# Remove the file from all commits
bfg --delete-files .env
# Clean up
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# Force push
git push --force
Most important:
- Immediately revoke/regenerate the exposed keys
- Add
.envto.gitignore - Never commit secrets again
Lesson learned: Always have a .gitignore BEFORE your first commit. Create it from gitignore.io for your tech stack.
Mistake #5: "Help, I Force Pushed to Main"
git push --force origin main
# *Immediate regret*
I overwrote the entire main branch. My team was... not happy.
The fix (if you catch it quickly):
# Find the commit you want to restore
git reflog
# You'll see something like:
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# e4f5g6h HEAD@{1}: commit: The good commit you want back
# Reset to that commit
git reset --hard e4f5g6h
# Force push to restore
git push --force origin main
Prevention:
# Protect main branch on GitHub
# Settings → Branches → Add rule → Require pull request reviews
Or configure Git to prevent force push:
# In your repo
git config branch.main.pushRemote no_push
Lesson learned: Never force push to shared branches. Just don't. If you think you need to, you probably don't.
Mistake #6: "I Deleted a Branch I Still Needed"
git branch -D feature-login
# Wait... I wasn't done with that
The fix:
# View recently deleted branches
git reflog
# Find the commit where the branch was
# It'll look like: a1b2c3d HEAD@{2}: commit: Login feature working
# Recreate the branch
git checkout -b feature-login a1b2c3d
Lesson learned: Git rarely truly deletes anything. The reflog is your time machine.
Mistake #7: "My Commit Messages Are Useless"
My old commits:
"fix"
"update"
"asdfasdf"
"final version"
"final version 2"
"THIS ONE ACTUALLY WORKS"
These tell me nothing when I need to debug later.
Better commit messages:
# Bad
git commit -m "fix bug"
# Good
git commit -m "Fix login button not responding on mobile
- Added touch event listeners
- Increased button tap target size
- Tested on iOS Safari and Android Chrome"
My current template:
[Type]: Short summary (50 chars or less)
More detailed explanation if needed (wrap at 72 chars).
Explain WHAT and WHY, not HOW (code shows how).
Bullet points are fine
List what you changed and why
Fixes #123
Types I use: feat, fix, docs, style, refactor, test, chore
Lesson learned: Future you will thank present you for clear commit messages. Write them like you're explaining to a teammate.
Mistake #8: "I Have 50 Uncommitted Changes"
I used to work for hours, making tons of changes, then try to commit everything at once. Result? Impossible to review, hard to debug, messy history.
What I learned:
# Commit related changes separately
git add src/auth/login.js
git commit -m "Add login validation"
git add src/auth/signup.js
git commit -m "Add signup form"
# Not everything at once
git add . # DON'T do this with 50 files changed
Use git add -p for surgical commits:
git add -p src/App.js
# Git will show each change and ask:
# Stage this hunk [y,n,q,a,d,s,e,?]?
# y = yes, n = no, s = split into smaller hunks
This lets you commit parts of a file separately. Game-changer.
Lesson learned: Commit early, commit often. Small, focused commits are easier to review, debug, and revert if needed.
Mistake #9: "I Forgot to Pull Before Pushing"
git push origin main
# error: failed to push some refs to 'origin'
# hint: Updates were rejected because the remote contains work that you do not have locally
The wrong fix:
git push --force # NOOO
The right fix:
# Pull and merge
git pull origin main
# Or pull and rebase (cleaner history)
git pull --rebase origin main
# Then push
git push origin main
Even better - make it automatic:
# Configure Git to always rebase on pull
git config pull.rebase true
Lesson learned: Always pull before pushing. Make it a habit: pull → code → commit → pull again → push.
Mistake #10: "I Don't Know What I Changed"
Ever made a bunch of changes and forgot what you did?
Commands that saved me:
# See what changed (before staging)
git diff
# See what's staged
git diff --staged
# See changes in a specific file
git diff src/App.js
# See who changed what (line by line)
git blame src/App.js
# See commit history with changes
git log -p
# See visual branch history
git log --oneline --graph --all
My favorite combo:
# Beautiful commit history
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
I made an alias for this:
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# Now just use:
git lg
Lesson learned: Git has amazing tools to show you what changed. Use them before committing.
Tools That Made Git Less Painful
1. VSCode Git Integration
- Visual diff viewer
- Merge conflict resolver
- Stage/unstage with clicks
- Built-in Git Graph extension
2. GitKraken or GitHub Desktop
- Visual interface for Git
- Great for beginners
- Makes branching/merging intuitive
3. Oh My Zsh (for terminal)
# Shows current branch, dirty state, etc.
# My prompt: user@computer feature-login ±
4. Git Aliases
# My essential aliases
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
My Current Git Workflow (After All These Mistakes)
# 1. Always start from main
git checkout main
git pull origin main
# 2. Create feature branch
git checkout -b feature-name
# 3. Make small, focused commits
git add specific-files
git commit -m "Clear message"
# 4. Pull main regularly to avoid conflicts
git checkout main
git pull origin main
git checkout feature-name
git merge main
# 5. When feature is done
git checkout main
git pull origin main
git merge feature-name
git push origin main
# 6. Delete feature branch
git branch -d feature-name
The Bottom Line
Every Git mistake I made taught me something valuable. The panic, the late nights debugging, the embarrassment of force-pushing to main—all of it made me a better developer.
Git is powerful but unforgiving. It won't stop you from shooting yourself in the foot. But it will help you recover (most of the time) if you know where to look.
My advice:
- Practice in a test repo first - Break things on purpose and learn to fix them
- Read error messages - They're usually helpful (unlike some languages I won't name)
- Use Git GUI tools - There's no shame in using visual tools while learning
- Commit often - Small commits are easier to manage and undo
- Don't be afraid to ask - Everyone has Git horror stories
And remember: Git is just a tool. It's there to help you, not to make your life miserable. Once you get past the initial learning curve, it becomes second nature.
What's the worst Git mistake you've made? Let's share our horror stories in the comments—misery loves company! 😅
Top comments (0)