DEV Community

Kirill Tolmachev
Kirill Tolmachev

Posted on • Edited on

7 Git Commands That Make You Look Like a Wizard

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. You ran git reset --hard and watched your work vanish. You 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.

The 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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

With 1000 commits between your good and bad state, you'll find the culprit in about 10 steps. It literally does 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
Enter fullscreen mode Exit fullscreen mode

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.

The scenario: You're halfway through a feature, but you also fixed a bug you noticed along the way. You want to commit the bugfix 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 bugfix
git add -A && git commit -m "fix: null check on user session"

# Bring your feature work back
git stash pop
Enter fullscreen mode Exit fullscreen mode

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.

The 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.
Enter fullscreen mode Exit fullscreen mode

squash merges into the previous commit and lets you rewrite the message. fixup does the same but silently keeps the original message. reword lets you change a commit message without touching the code. edit pauses the rebase so you can amend the commit.

Your PR goes from looking like a crime scene to looking like you wrote it perfectly the first time. Nobody needs to know the truth.

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
Enter fullscreen mode Exit fullscreen mode

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 hotfix commit
git push origin main
# Crisis resolved. Deploy.
Enter fullscreen mode Exit fullscreen mode

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 tradeoff. 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

# 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
Enter fullscreen mode Exit fullscreen mode

-S finds commits where the count of occurrences changed. -G finds 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
Enter fullscreen mode Exit fullscreen mode

This gives you a visual branch topology right in your terminal. Alias it to git lg and you'll never open a GUI git client again. (Okay, sometimes. But 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.

The scenario: You're deep into a feature branch. Your PM pings: "critical bug on main, need a fix NOW." You've got unstaged experiments everywhere and you really don't want to deal with stashing all of it.

# Create a new worktree for the hotfix, 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
Enter fullscreen mode Exit fullscreen mode

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 hotfix 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, they've been there for years. The reason they make you look like a wizard is because 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. 🧙‍♂️

Top comments (1)

Collapse
 
francistrdev profile image
👾 FrancisTRᴅᴇᴠ 👾

Great post! Keeping this bookmark for later use since I have been using GitHub Desktop to do the flow instead of doing it in the terminal. Nice work!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.