Advanced Git

Rebase, cherry-pick, stash, reset, reflog

Git Stash

Stash = Temporarily save uncommitted changes. Perfect when you need to switch branches but aren’t ready to commit.

Basic Stash

# Save current changes
git stash

# Your working directory is now clean
git status  # Nothing to commit

# Switch branches, do other work...
git checkout other-branch

# Come back and restore changes
git checkout original-branch
git stash pop  # Restores and removes from stash

Stash with Message

# Name your stash (easier to find later)
git stash save "WIP: login validation"

# Or modern syntax
git stash push -m "WIP: login validation"

Managing Multiple Stashes

# List all stashes
git stash list
# stash@{0}: WIP: login validation
# stash@{1}: WIP: fixing header

# Apply specific stash (keep in list)
git stash apply stash@{1}

# Apply and remove specific stash
git stash pop stash@{1}

# Delete a stash
git stash drop stash@{0}

# Clear all stashes
git stash clear

Git Rebase

Rebase = Move your branch to start from a different commit. Creates a cleaner, linear history compared to merge.

Rebase vs Merge

MERGE (creates merge commit):
main:    A ─── B ─── C ─── M
              \           /
feature:       D ─── E ──

REBASE (linear history):
main:    A ─── B ─── C
                      \
feature:               D' ─── E'

Basic Rebase

# On your feature branch
git checkout feature

# Rebase onto main (move feature to tip of main)
git rebase main

# If conflicts occur:
# 1. Fix conflicts in files
# 2. git add .
# 3. git rebase --continue

# Abort if things go wrong
git rebase --abort

Interactive Rebase

Edit, squash, reorder, or drop commits:

# Rebase last 3 commits
git rebase -i HEAD~3

This opens an editor:

pick abc1234 Add login form
pick def5678 Fix typo in login
pick ghi9012 Add validation

# Commands:
# p, pick = use commit
# r, reword = edit commit message
# e, edit = stop to amend commit
# s, squash = combine with previous commit
# f, fixup = squash but discard message
# d, drop = remove commit

Squash Commits

# Combine last 3 commits into one
git rebase -i HEAD~3

# Change 'pick' to 'squash' (or 's'):
pick abc1234 Add login form
squash def5678 Fix typo in login
squash ghi9012 Add validation

# Save and edit the combined commit message

Cherry Pick

Cherry-pick = Copy a specific commit to your current branch. Grab just the commits you need without merging everything.

# Copy one commit
git cherry-pick abc1234

# Copy multiple commits
git cherry-pick abc1234 def5678

# Copy a range of commits
git cherry-pick abc1234..ghi9012

Common Use Cases

# Hotfix: Apply bugfix from develop to main
git checkout main
git cherry-pick abc1234  # The bugfix commit

# Oops: Wrong branch - move commit to correct branch
git checkout correct-branch
git cherry-pick abc1234
git checkout wrong-branch
git reset --hard HEAD~1  # Remove from wrong branch

Cherry-Pick Options

# Don't commit automatically (stage only)
git cherry-pick -n abc1234

# Edit commit message
git cherry-pick -e abc1234

# If conflicts, after resolving:
git cherry-pick --continue

# Abort cherry-pick
git cherry-pick --abort

Reset vs Revert

Two ways to undo changes. Different purposes.

Git Reset (Rewrite History)

# Soft: Undo commit, keep changes staged
git reset --soft HEAD~1

# Mixed (default): Undo commit, keep changes unstaged
git reset HEAD~1

# Hard: Undo commit AND discard changes ⚠️
git reset --hard HEAD~1
Before: A ─── B ─── C ─── D (HEAD)

git reset --hard HEAD~2

After:  A ─── B (HEAD)
        C and D are gone!

Git Revert (Safe Undo)

Creates a new commit that undoes a previous commit. Safe for shared branches.

# Revert a specific commit
git revert abc1234

# Revert without auto-commit
git revert -n abc1234
Before: A ─── B ─── C ─── D (HEAD)

git revert C

After:  A ─── B ─── C ─── D ─── C' (HEAD)
        C' undoes C's changes

Git Reflog (Your Safety Net)

Reflog = Reference log. Records every move HEAD makes. Even after reset --hard, your commits aren’t truly gone.

View Reflog

git reflog

# Output:
# abc1234 HEAD@{0}: reset: moving to HEAD~2
# def5678 HEAD@{1}: commit: Add feature X
# ghi9012 HEAD@{2}: commit: Fix bug Y
# jkl3456 HEAD@{3}: checkout: moving from main to feature

Recover “Lost” Commits

# Oops! Accidentally reset --hard
git reset --hard HEAD~3  # Deleted 3 commits!

# Find them in reflog
git reflog
# abc1234 HEAD@{1}: commit: Important work

# Recover!
git reset --hard abc1234
# Or create a branch at that point
git branch recovered abc1234

Recover Deleted Branch

# Deleted a branch by mistake
git branch -D feature-important  # Oops!

# Find it
git reflog | grep feature-important
# Shows: checkout: moving from feature-important

# Find the commit hash and recreate
git branch feature-important abc1234

Amend & Fixup

Amend Last Commit

# Fix last commit message
git commit --amend -m "Better message"

# Add forgotten file to last commit
git add forgotten-file.js
git commit --amend --no-edit  # Keep same message

# Change author of last commit
git commit --amend --author="Name <email@example.com>"

Fixup Older Commits

# Create a fixup commit
git commit --fixup abc1234

# Later, squash all fixups automatically
git rebase -i --autosquash main

Git Bisect (Bug Hunt)

Bisect = Binary search through commits to find when a bug was introduced. Tests hundreds of commits in just a few steps.

# Start bisect
git bisect start

# Mark current commit as bad (has bug)
git bisect bad

# Mark a known good commit (before bug existed)
git bisect good abc1234

# Git checks out middle commit
# Test if bug exists, then:
git bisect good  # No bug
# or
git bisect bad   # Bug exists

# Repeat until Git finds the culprit
# "abc1234 is the first bad commit"

# Done - return to normal
git bisect reset

Automate with Script

# Run a test script automatically
git bisect start HEAD abc1234
git bisect run npm test

# Git will find the commit that broke the tests!

Cleanup & Maintenance

Remove Untracked Files

# See what would be deleted (dry run)
git clean -n

# Delete untracked files
git clean -f

# Delete untracked files AND directories
git clean -fd

# Delete ignored files too
git clean -fdx

Garbage Collection

# Optimize repository
git gc

# Aggressive cleanup (slower but thorough)
git gc --aggressive

Check Repository Health

# Verify integrity
git fsck

# Show repository size
git count-objects -vH

Quick Reference

# Stash
git stash                    # Save changes
git stash pop                # Restore and remove
git stash list               # List all stashes
git stash drop stash@{0}     # Delete stash

# Rebase
git rebase main              # Rebase onto main
git rebase -i HEAD~3         # Interactive rebase
git rebase --abort           # Cancel rebase

# Cherry-pick
git cherry-pick <commit>     # Copy commit
git cherry-pick -n <commit>  # Stage only, don't commit

# Reset
git reset --soft HEAD~1      # Undo commit, keep staged
git reset HEAD~1             # Undo commit, keep changes
git reset --hard HEAD~1      # Undo commit, discard all

# Revert
git revert <commit>          # Create undo commit

# Recovery
git reflog                   # View all HEAD movements
git reset --hard <hash>      # Recover to any point

# Amend
git commit --amend           # Edit last commit
git commit --amend --no-edit # Add to last commit

# Bisect
git bisect start             # Start bug hunt
git bisect good/bad          # Mark commits
git bisect reset             # End bisect

Practice Exercise

# Setup
mkdir advanced-practice && cd advanced-practice
git init
echo "v1" > file.txt && git add . && git commit -m "v1"
echo "v2" > file.txt && git commit -am "v2"
echo "v3" > file.txt && git commit -am "v3"
echo "v4" > file.txt && git commit -am "v4"

# Exercise 1: Stash
echo "work in progress" >> file.txt
git stash
git stash list
git stash pop

# Exercise 2: Interactive Rebase (squash v2,v3,v4 into one)
git rebase -i HEAD~3
# Change 'pick' to 'squash' for last two commits

# Exercise 3: Reset and Recover
git log --oneline  # Note the commit hash
git reset --hard HEAD~1  # "Lose" a commit
git reflog  # Find it
git reset --hard <hash>  # Recover!

# Exercise 4: Amend
git commit --amend -m "Better commit message"