← Back to Blog

Git Beyond the Basics: Tricks That Actually Save My Day

Most developers learn git add, git commit, git push, and call it done. But git is a remarkably deep tool, and the commands most people never learn are exactly the ones that save the most time. Here are the git techniques I actually use to recover from mistakes, understand history, and move faster.


git reflog: Your Time Machine

git reflog is the most underused command in git. It records every movement of HEAD — including commits, resets, and checkouts — even if you have overwritten history.

git reflog

Output looks like this:

a3b1c2d HEAD@{0}: reset: moving to HEAD~2
f7e9d1a HEAD@{1}: commit: add user profile endpoint
c4a8b3e HEAD@{2}: commit: fix validation bug

Accidentally ran git reset --hard and lost commits? Find the commit hash in reflog and recover:

git checkout f7e9d1a
# or to restore your branch
git reset --hard f7e9d1a

reflog has saved me from “I just deleted an hour of work” panic more times than I can count.


git bisect: Binary Search for Bugs

You know a bug was introduced somewhere between last week and today, but you have 60 commits in between and no idea which one is the culprit. git bisect automates a binary search through your history.

git bisect start
git bisect bad                  # current commit is broken
git bisect good v1.2.0          # this version worked fine

Git checks out a commit in the middle. You test whether the bug is present, then tell git:

git bisect bad    # bug is still here
# or
git bisect good   # bug is not here

Git narrows the range by half each time. In about 6 rounds, you will pinpoint the exact commit that introduced the bug — out of 60 candidates.

When done:

git bisect reset  # return to original HEAD

git stash: More Than Just Saving Work

Most developers know git stash saves uncommitted changes. Fewer know about the useful flags:

# Stash with a description (essential for multiple stashes)
git stash push -m "wip: user auth refactor"

# Stash only staged changes
git stash push --staged

# List stashes
git stash list

# Apply a specific stash without removing it
git stash apply stash@{2}

# Apply and drop in one command
git stash pop

# Stash untracked files too
git stash push --include-untracked

The -m flag is critical. A stash named “WIP on main: 3f8d9a fix button” tells you nothing in two weeks. Name your stashes.


git rebase -i: Rewriting History Cleanly

Interactive rebase lets you clean up commits before merging into main. Useful for combining “WIP”, “fix typo”, and “actually fix it” commits into one coherent commit.

# Rebase the last 4 commits interactively
git rebase -i HEAD~4

An editor opens with your commits listed. Change pick to:

  • squash (or s) — combine with previous commit
  • reword (or r) — edit the commit message
  • drop (or d) — delete the commit entirely
  • edit (or e) — stop to amend the commit
pick f7e9d1a add user profile endpoint
squash c4a8b3e fix validation bug
squash a3b1c2d fix again
reword b2c4d5e update tests

The result: a clean, readable history instead of a trail of “oops” commits.


git worktree: Multiple Branches at Once

git worktree lets you check out multiple branches simultaneously in different directories — without stashing or committing half-finished work.

# Create a worktree for a hotfix branch
git worktree add ../project-hotfix hotfix/login-bug

# Work in the new directory without touching your main checkout
cd ../project-hotfix
# ... fix the bug, commit, push ...

# Clean up when done
git worktree remove ../project-hotfix

This is invaluable when you are deep in a feature branch and a production bug comes in that needs an immediate fix. No stashing, no context switching drama.


git log: Finding Things Faster

The default git log output is noisy. These flags make it actually useful:

# Compact one-line view with graph
git log --oneline --graph --decorate

# Search commit messages
git log --grep="authentication"

# Find commits that changed a specific function
git log -L :functionName:path/to/file.ts

# See what changed in a specific file over time
git log --follow -p src/components/Button.tsx

# Find who wrote a specific line (blame with context)
git blame -L 42,55 src/utils/auth.ts

The -L :functionName:file flag is particularly useful — it shows you the entire history of changes to a specific function, not just the file.


git cherry-pick: Grab One Commit From Anywhere

If you committed something to the wrong branch and need to bring it to another branch without merging everything:

# Get the commit hash from git log or reflog
git cherry-pick a3b1c2d

# Cherry-pick without committing (apply as staged changes)
git cherry-pick --no-commit a3b1c2d

# Cherry-pick a range of commits
git cherry-pick a3b1c2d..f7e9d1a

Useful Aliases to Set Up Once

Add these to your ~/.gitconfig and save yourself keystrokes every day:

[alias]
  st = status
  co = checkout
  br = branch
  lg = log --oneline --graph --decorate --all
  undo = reset HEAD~1 --mixed
  amend = commit --amend --no-edit
  aliases = config --get-regexp alias

git undo is the one I use most — it un-commits the last commit while keeping your changes staged, so you can fix something and recommit cleanly.


Conclusion

Git rewards investment. Spending a few hours with these commands will save you time every week for the rest of your career. The most important ones to internalize first: reflog for recovering from mistakes, bisect for tracking down bugs, and rebase -i for keeping your history readable.

The rest will come when you need them. Now you know they exist.