7 Git Commands That Make You Look Like a Wizard
Source: Dev.to
You know what actually separates the devs who look like they know what they’re doing from the ones who just Google “how to undo git commit” every other day?
It’s not knowing fancy algorithms or memorizing design patterns. It’s knowing your way around Git beyond add, commit, push, and panic‑googling merge conflicts.
I’m talking about the commands that make your pair‑programming partner stop and go, “wait, you can do that?” The deep cuts that turn a 30‑minute disaster recovery into a 10‑second flex.
1. git reflog – The undo button you didn’t know existed
Every developer has that moment: you force‑pushed to the wrong branch, ran git reset --hard and watched your work vanish, or rebased and now your commit history looks like abstract art.
You think it’s gone. It’s not.
git reflog is Git’s flight recorder. It tracks every single thing HEAD has pointed to, even stuff that’s no longer in any branch. Deleted commits, abandoned rebases, force‑push casualties – they’re all in there.
Scenario: You just ran git reset --hard HEAD~3 and immediately realized you nuked the wrong commits. Your stomach drops. Three hours of work, gone.
# See everything HEAD has ever pointed to
git reflog
Output looks like:
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
f4e5d6c HEAD@{1}: commit: implement payment webhook
7g8h9i0 HEAD@{2}: commit: add Stripe integration
j1k2l3m HEAD@{3}: commit: refactor checkout flow
Just… go back.
git reset --hard f4e5d6c
That’s it. Your commits are back. No sweat. While everyone else is panicking and cloning fresh repos, you’re casually restoring history like a time traveler.
Pro tip: Reflog entries expire after 90 days by default, so don’t wait three months to realize you need something back.
2. git bisect – Let Git find the bug for you
Picture this: your CI is green, your tests pass, but somewhere in the last 47 commits the login page started rendering upside‑down on Firefox. Nobody knows which commit broke it.
You could check out each commit one by one like an animal. Or you could let Git do a binary search through your history automatically.
# Start the hunt
git bisect start
# Mark current (broken) state as bad
git bisect bad
# Mark a known good commit (maybe last week’s release tag)
git bisect good v2.3.1
Git checks out the middle commit. You test it.
# If it’s broken:
git bisect bad
# If it works:
git bisect good
Repeat. Git narrows it down in log₂(n) steps.
47 commits? That’s ~6 checks, not 47.
With 1 000 commits between your good and bad state, you’ll find the culprit in about 10 steps. It literally does a binary search on your commit history. This is Computer Science™ actually being useful for once.
Next level: If you have a test script that can determine good/bad automatically:
git bisect start HEAD v2.3.1
git bisect run ./test-login-page.sh
Go grab a coffee. Git will find the exact commit that broke it while you’re gone. You come back, point at the guilty commit, and look like Sherlock Holmes with a terminal.
3. git stash -p – Surgical stashing
Everyone knows git stash. But most people use it like a sledgehammer: stash everything, pray it comes back right.
The -p flag (for patch) lets you interactively choose which hunks to stash. You know, for when you’ve been working on two things at once (don’t pretend you don’t) and need to commit one without the other.
Scenario: You’re halfway through a feature, but you also fixed a bug you noticed along the way. You want to commit the bug‑fix now and keep working on the feature.
# Interactively pick what to stash
git stash -p
Git shows you each change one by one:
Stash this hunk [y,n,q,a,d,s,e,?]?
y = stash this hunk
n = keep this hunk (don’t stash)
s = split into smaller hunks
q = quit (done selecting)
Now your working directory only has the bug‑fix.
git add -A && git commit -m "fix: null check on user session"
Bring your feature work back:
git stash pop
The s option is the secret sauce: it splits a hunk into even smaller pieces when Git grouped two changes together. Precision surgery on your working tree.
Bonus combo:
git stash -p -m "WIP: auth refactor"
lets you stash selectively and give it a name so you’re not playing “which stash was which?” roulette three days later.
4. git rebase -i – Rewrite history like you meant to
Interactive rebase is the single most powerful Git command, and also the one most people are scared of. Stop being scared. It’s just editing a TODO list.
You can squash commits, reorder them, reword messages, drop commits entirely, or edit them in place. It’s your commit history in a text editor, and you’re the god of that file.
Scenario: You made 6 commits while building a feature, and three of them are “fix typo”, “WIP”, and “actually fix the thing I said I fixed”. You don’t want that in the permanent record.
# Rebase the last 6 commits interactively
git rebase -i HEAD~6
Your editor opens with:
pick a1b2c3d add user authentication
pick d4e5f6g WIP: trying stuff
pick h7i8j9k fix typo in auth middleware
pick l0m1n2o actually implement auth middleware
pick p3q4r5s add auth tests
pick t6u7v8w fix test assertion
Change it to:
pick a1b2c3d add user authentication
squash d4e5f6g WIP: trying stuff
squash h7i8j9k fix typo in auth middleware
squash l0m1n2o actually implement auth middleware
pick p3q4r5s add auth tests
fixup t6u7v8w fix test assertion
Save and close. Now you have a clean, professional history.
squashmerges the commit into the previous one and lets you rewrite the message.fixupmerges without prompting for a new message.
5. git cherry-pick: Steal From Other Branches
Sometimes you need exactly one commit from another branch. Not a merge, not a rebase—just that one fix your coworker pushed to develop that you desperately need on your feature branch right now.
# Grab a specific commit by its hash
git cherry-pick a1b2c3d
# Need multiple commits? Sure.
git cherry-pick a1b2c3d f4e5d6c
# Cherry‑pick without committing (stage the changes only)
git cherry-pick --no-commit a1b2c3d
The scenario that actually happens: Production is on fire. The fix exists in the develop branch, buried under 30 other commits that aren’t ready for production. You need the fix, not the 30 other things.
git checkout main
git cherry-pick d4e5f6a # just the hot‑fix commit
git push origin main
Watch out: Cherry‑picking creates a new commit with the same changes but a different hash. If you later merge the source branch, Git is usually smart enough to handle it, but occasionally you’ll get a duplicate‑looking conflict. That’s the trade‑off. Worth it.
6. git log -S: Search Through All of Time
git log by itself is boring. git log --oneline is slightly less boring. But git log -S is a time machine with a search bar.
The -S flag (called the pickaxe) searches through the content of every diff in your history—not commit messages, actual code changes. It finds commits where a specific string was added or removed.
The scenario: Someone deleted the validatePayment() function. No one knows when, no one knows why, and git blame doesn’t help because the file’s been refactored six times since then.
# Find every commit that added or removed "validatePayment"
git log -S "validatePayment" --oneline
Sample output
f4e5d6c remove legacy payment validation
a1b2c3d refactor: extract payment validation
9z8y7x6 add payment validation to checkout
# Want to see the actual diff?
git log -S "validatePayment" -p
# Search with regex instead
git log -G "validate.*Payment" --oneline
-Sfinds commits where the count of occurrences changed.-Gfinds commits where the string appears anywhere in the diff (even if the count didn’t change).
For most detective work, -S is what you want.
The power combo nobody talks about
git log --all --oneline --graph --decorate
This gives you a visual branch topology right in your terminal. Alias it to git lg and you’ll rarely need a GUI Git client again (okay, sometimes, but far less often).
7. git worktree: Be in Two Places at Once
This one is genuinely underrated. git worktree lets you check out multiple branches simultaneously in separate directories, all sharing the same .git data. No more stashing, no more cloning the repo twice, no more committing half‑finished work just to switch branches.
Scenario: You’re deep into a feature branch. Your PM pings: “critical bug on main, need a fix NOW.” You have unstaged experiments everywhere and you really don’t want to deal with stashing all of it.
# Create a new worktree for the hot‑fix, checking out main
git worktree add ../hotfix-login main
Now you have:
/projects/myapp → your feature branch (untouched)
/projects/hotfix-login → main branch, ready to fix
cd ../hotfix-login
# Fix the bug, commit, push. Your feature branch is completely undisturbed.
When you’re done, clean up:
cd ../myapp
git worktree remove ../hotfix-login
This is wildly better than git stash for context switches. Your feature branch stays exactly as you left it—dirty files, open editor tabs, everything. The hot‑fix happens in a completely separate directory.
I use this almost daily when doing code reviews, too. I can check out a teammate’s branch in a separate worktree, run it, poke at it, while my own work stays untouched. Game changer.
The Actual Wizard Move
None of these commands are “advanced.” They’re all in the docs and have been there for years. The reason they make you look like a wizard is that most developers never bother to learn past add, commit, push, pull, and panic‑googling merge conflicts.
You don’t have to memorize all of these today. Just pick one. Next time you’re in a Git mess, try it instead of nuking the repo and cloning fresh. That’s how you level up: one “oh no” moment at a time.
Got a Git trick that’s saved you? Drop it in the comments. I’m always looking for new spells. 🧙♂️