Everyone knows git add, git commit, git push. The developers who treat git as a superpower know about a dozen more commands that make complex workflows feel easy and make “I accidentally deleted my work” feel recoverable.
reflog: Your Safety Net
The reflog records every position HEAD has been at, even after resets and rebases. It is a time machine.
git reflog
# Output:
# abc1234 HEAD@{0}: reset: moving to HEAD~1
# def5678 HEAD@{1}: commit: Add user authentication
# ghi9012 HEAD@{2}: commit: Fix navigation bug
# Oops, you reset away a commit you needed
git checkout def5678
# or
git reset --hard HEAD@{1}
git reflog works even after git reset --hard. Entries expire after 90 days by default. If your commit happened in the last 90 days, it is recoverable.
bisect: Binary Search Your Bugs
You know the app worked in commit A. It does not work in commit B. There are 200 commits between them. git bisect performs a binary search to find the exact commit that introduced the bug.
git bisect start
git bisect bad # Current commit is broken
git bisect good v1.2.0 # This version worked
# Git checks out a commit halfway between
# Test it, then tell git the result:
git bisect good # or git bisect bad
# Git keeps halving the range
# After ~8 rounds it identifies the exact bad commit
git bisect reset # Return to original state
200 commits requires about 8 rounds instead of 200 manual checkouts. For hard-to-reproduce bugs where you know a regression window, this is invaluable.
Automate it with a test script:
git bisect run npm test # Runs test, uses exit code to determine good/bad
worktree: Multiple Branches at Once
Switching branches to review a PR while in the middle of feature work means stashing or committing. git worktree lets you check out a branch in a separate directory, both active at the same time.
git worktree add ../hotfix-branch main
cd ../hotfix-branch
# Work on the hotfix
git commit -am "Fix critical bug"
cd ../my-main-project
# Your feature work is exactly where you left it
git worktree remove ../hotfix-branch
Each worktree is a full working directory with its own index. Both can be open in separate terminal sessions simultaneously. No stashing, no context loss.
stash with a name
Stash stores uncommitted work. Most people use it as a single slot. It is actually a stack with labels.
git stash push -m "WIP: user auth refactor"
git stash push -m "experiment: caching approach"
git stash list
# stash@{0}: On main: experiment: caching approach
# stash@{1}: On main: WIP: user auth refactor
git stash pop stash@{1} # Apply specific stash
git stash show -p stash@{0} # View a stash diff
The unnamed stash pattern means you lose track of what you stashed. Named stashes are legible days later.
interactive rebase: Rewrite History Cleanly
Before pushing a branch, clean up the commit history. Interactive rebase lets you reorder, squash, edit, and split commits.
git rebase -i HEAD~5 # Rewrite last 5 commits
# Opens an editor:
# pick abc1234 Initial implementation
# pick def5678 Fix typo
# pick ghi9012 Fix another typo
# pick jkl3456 Refactor auth logic
# pick mno7890 Add tests
# Change to:
# pick abc1234 Initial implementation
# squash def5678 Fix typo <- merge into previous
# squash ghi9012 Fix another typo <- merge into previous
# pick jkl3456 Refactor auth logic
# pick mno7890 Add tests
Clean history makes code review faster and git log useful. Do not rebase commits that others have already pulled.
cherry-pick: Port Specific Commits
When a bug fix is on a feature branch and needs to go to main without the entire feature:
git log feature/payment # Find the commit hash
git checkout main
git cherry-pick abc1234 # Apply that specific commit
Cherry-pick applies the diff from the specified commit to the current branch. Use it for backporting fixes or moving specific changes between branches without a full merge.
add -p: Surgical Staging
Committing all changes at once produces commits that mix unrelated work. git add -p (patch mode) lets you stage changes hunk by hunk.
git add -p
# For each hunk:
# y - stage this hunk
# n - skip this hunk
# s - split into smaller hunks
# e - manually edit the hunk
The result is atomic commits that contain only related changes. Code review becomes easier. git bisect becomes more useful. History tells a coherent story.
log with the good flags
Plain git log is barely useful. With the right flags:
git log --oneline --graph --decorate --all
# Shows branching structure visually
git log --author="Chirag" --since="2 weeks ago" --oneline
# Your recent commits
git log -S "function authenticateUser" --oneline
# Commits that added or removed this exact string
git log --follow -- path/to/file.ts
# File history including renames
Bottom Line
The gap between git users who know add/commit/push and those who know reflog/bisect/worktree/rebase -i is a gap in daily productivity. Nothing here is arcane - these are standard git features that solve real problems that come up every week. Add them gradually: start with reflog (it will save you soon), then add -p (it will improve your commits), then bisect (it will find your next regression in minutes instead of hours).
Comments