Skip to main content

05 - Git Advanced Commands: Stash, Reflog and Bisect

Discover essential advanced Git commands: stash for temporary work, reflog for recovery, bisect for debugging and worktree for multiple branches.

What do you think about this article?

At a Glance

Discover essential advanced Git commands: stash for temporary work, reflog for recovery, bisect for debugging and worktree for multiple branches.

Git Advanced Commands: Stash, Reflog, and Bisect

Beyond basic commands (commit, push, merge), Git offers advanced tools for managing complex workflows, recovering lost work, and debugging issues. Git stash saves temporary work, reflog is your lifesaver for recovery, and bisect finds bugs with binary search. Mastering these commands makes you a Git power user.

🎯 What You'll Learn

  • Git stash for saving temporary work
  • Git reflog for recovering "lost" commits
  • Git bisect for finding commits that introduced bugs
  • Worktree and submodules (bonus)

Git Stash: Your Temporary Notepad

git stash saves uncommitted changes in a temporary "stash", cleaning the working directory. Useful when you need to switch branches quickly but current work isn't ready for a commit.

Basic Stash
# Situation: you're working on feature but urgent hotfix arrives
git status
# modified: src/component.ts
# modified: src/style.css

# Save changes to stash
git stash
# Output: Saved working directory and index state WIP on feature: abc1234 last commit

# Working directory is now clean
git status
# nothing to commit, working tree clean

# Switch branch and work on hotfix
git checkout main
# ... work on hotfix ...

# Return to feature branch
git checkout feature

# Recover changes from stash
git stash pop
# Reapply changes and remove the stash

Advanced Stash

Stash Operations
# Stash with descriptive message
git stash save "WIP: refactoring authentication"

# Stash including untracked files
git stash -u

# Stash including everything (even .gitignore)
git stash -a

# List all stashes
git stash list
# stash@{{ '{' }}0{{ '}' }}: WIP on feature: abc1234 refactoring auth
# stash@{{ '{' }}1{{ '}' }}: On main: def5678 emergency fix
# stash@{{ '{' }}2{{ '}' }}: WIP on develop: ghi9012 new feature

# View stash content
git stash show stash@{{ '{' }}0{{ '}' }}
git stash show -p stash@{{ '{' }}0{{ '}' }}  # With full diff

# Apply stash without removing it
git stash apply stash@{{ '{' }}1{{ '}' }}

# Remove specific stash
git stash drop stash@{{ '{' }}0{{ '}' }}

# Remove all stashes
git stash clear

# Create branch from stash
git stash branch new-feature-branch stash@{{ '{' }}0{{ '}' }}

Partial Stash

You can save only some files to stash, keeping others in the working directory:

Interactive Stash
# Interactive stash: choose what to save
git stash -p
# For each hunk:
# y = stash this hunk
# n = do not stash this hunk
# q = quit
# a = stash this and all remaining hunks
# d = do not stash this or any remaining hunks

# Stash only specific files
git stash push -m "Save only component" src/component.ts

# Stash everything except specific files (path spec)
git stash push -- '*.ts' '!src/test.ts'

Git Reflog: Your Lifesaver

git reflog records every HEAD movement, even deleted commits, resets, aborted rebases. It's the backup that saves you when you think you've lost everything.

Viewing Reflog
# View HEAD reflog
git reflog
# abc1234 HEAD@{{ '{' }}0{{ '}' }}: commit: fix bug
# def5678 HEAD@{{ '{' }}1{{ '}' }}: checkout: moving from main to feature
# ghi9012 HEAD@{{ '{' }}2{{ '}' }}: reset: moving to HEAD~1
# jkl3456 HEAD@{{ '{' }}3{{ '}' }}: commit: add feature
# mno7890 HEAD@{{ '{' }}4{{ '}' }}: commit: initial commit

# Reflog of specific branch
git reflog show feature

# Reflog with dates
git reflog --date=relative
git reflog --date=iso

Recovery with Reflog

Practical examples of how reflog saves your work:

Scenario 1: Accidental Reset
# You did a reset and lost commits
git reset --hard HEAD~3
# Oh no! I only wanted HEAD~1

# Find lost commits in reflog
git reflog
# abc1234 HEAD@{{ '{' }}0{{ '}' }}: reset: moving to HEAD~3
# def5678 HEAD@{{ '{' }}1{{ '}' }}: commit: important feature ← I WANT THIS!

# Recover the commit
git reset --hard def5678
# Or
git reset --hard HEAD@{{ '{' }}1{{ '}' }}

# Commits recovered!
Scenario 2: Deleted Branch
# You delete branch by mistake
git branch -D feature-important
# Deleted branch feature-important (was abc1234).

# Oh no! Need to recover it
git reflog
# Find last commit of deleted branch
# abc1234 HEAD@{{ '{' }}5{{ '}' }}: commit: last commit on feature

# Recreate the branch
git branch feature-important abc1234

# Branch recovered!
Scenario 3: Disastrous Rebase
# Rebase goes wrong, you abort but lose work
git rebase --abort

# Find state before rebase
git reflog
# def5678 HEAD@{{ '{' }}1{{ '}' }}: rebase: aborting ← corrupted state
# ghi9012 HEAD@{{ '{' }}2{{ '}' }}: checkout: moving from feature to main
# abc1234 HEAD@{{ '{' }}3{{ '}' }}: commit: my work ← GOOD STATE

# Return to pre-rebase state
git reset --hard abc1234

Git Bisect: Debugging with Binary Search

git bisect uses binary search to find which commit introduced a bug. Instead of manually checking hundreds of commits, bisect finds the culprit in log(n) steps.

Bisect Workflow
# Situation: Bug exists now (HEAD) but didn't exist 10 days ago
# You have 100 commits in between: which introduced the bug?

# 1. Start bisect
git bisect start

# 2. Mark current commit as "bad" (has the bug)
git bisect bad

# 3. Mark old commit as "good" (didn't have the bug)
git bisect good abc1234

# Git checks out the commit in the middle
# Bisecting: 50 revisions left to test after this

# 4. Test if the bug exists
npm test
# If test fails:
git bisect bad
# If test passes:
git bisect good

# 5. Repeat until Git finds the culprit commit
# Bisecting: 25 revisions left...
# Bisecting: 12 revisions left...
# Bisecting: 6 revisions left...
# Bisecting: 3 revisions left...
# Bisecting: 1 revision left...

# def5678 is the first bad commit
# commit def5678
# Author: Developer <dev@example.com>
# Date: Mon Dec 1 10:00:00 2024
#
#     refactor: change authentication logic ← THIS IS THE CULPRIT

# 6. End bisect
git bisect reset
# HEAD returns to original branch

Automated Bisect

You can automate bisect with a test script:

Bisect with Script
# test.sh - script that returns 0 if OK, 1 if bug present
#!/bin/bash
npm test | grep "PASS"
exit $?

# Automatic bisect
git bisect start
git bisect bad HEAD
git bisect good abc1234
git bisect run ./test.sh

# Git automatically tests each commit and finds the culprit!
# Final output:
# def5678 is the first bad commit

Git Worktree: Multiple Simultaneous Branches

git worktree allows having multiple branches checked out simultaneously in different directories. Useful for working on hotfixes without stashing current work.

Basic Worktree
# Situation: you're on feature branch, urgent hotfix needed
# Instead of stash, create new worktree

# Create worktree for hotfix
git worktree add ../hotfix-worktree hotfix/critical-bug

# Now you have two directories:
# ./project (feature branch)
# ../hotfix-worktree (hotfix branch)

# Go to hotfix directory
cd ../hotfix-worktree
# Work on the fix
git commit -m "fix: critical bug"
git push

# Return to main project
cd ../project
# Continue work on feature without touching anything

# List worktrees
git worktree list
# /path/to/project          abc1234 [feature]
# /path/to/hotfix-worktree  def5678 [hotfix/critical-bug]

# Remove worktree when done
git worktree remove ../hotfix-worktree

Best Practices

✅ Stash

  • Use descriptive messages: git stash save "description"
  • Don't leave stashes for months (commit or discard)
  • Use git stash list regularly for cleanup

✅ Reflog

  • Check reflog before dangerous reset/rebase
  • Reflog is local, doesn't get pushed
  • Reflog cleans up after 90 days (configurable)

✅ Bisect

  • Automate with script for speed
  • Make sure "good" commit is really good
  • Use git bisect skip if a commit doesn't compile

Bonus Commands

Other Useful Commands
# Git fsck: verify repository integrity
git fsck
# Find corrupted or dangling objects

# Git gc: garbage collection (cleanup)
git gc --aggressive

# Git clean: remove untracked files
git clean -fd  # -f force, -d directories
git clean -n   # Dry run (see what would be removed)

# Git archive: create code archive
git archive --format=zip HEAD > code.zip

# Git blame: see who wrote each line
git blame file.ts
git blame -L 10,20 file.ts  # Only lines 10-20

# Git shortlog: contribution summary
git shortlog -sn  # -s summary, -n sorted by number

Conclusion

Git's advanced commands transform difficult situations into solvable problems. Stash manages temporary work, reflog recovers "lost" commits, and bisect finds bugs efficiently. Knowing these tools gives you confidence to explore, experiment, and recover from errors without fear.

🎯 Key Points

  • Stash saves temporary work: git stash / git stash pop
  • Reflog records everything: git reflog for recovery
  • Bisect finds bugs with binary search: git bisect start/good/bad
  • Worktree for multiple simultaneous branches
  • These commands save you in critical situations

Frequently asked questions

What is the purpose of using Git stash?

The purpose of using Git stash is to save uncommitted changes in a temporary "stash", cleaning the working directory, and allowing you to switch branches quickly.

How does Git reflog help with recovery?

Git reflog records every HEAD movement, even deleted commits, resets, and aborted rebases, serving as a backup that can recover lost work.

What is the main advantage of using Git bisect for debugging?

The main advantage of using Git bisect is its ability to find which commit introduced a bug efficiently, using binary search instead of manually checking hundreds of commits.

How does Git worktree allow you to manage multiple branches simultaneously?

Git worktree allows having multiple branches checked out simultaneously in different directories, making it useful for working on hotfixes without stashing current work.

Sources and further reading

Try These Tools

Free developer tools related to this topic.

Commenti

Caricamento commenti...

Sign in to comment

Discuss this article in the community

Join the Telegram group to discuss with other developers, ask questions and share your experiences.

Did you like this article?

Explore other content on the blog or discover my projects