Skip to main content

Managing History ⏱️

Master your Git history with powerful tools to undo, rewrite, and reshape your commit timeline. Use carefully on shared branches!

Undoing Changes ↩️

Undo Unstaged Changes

Restore file to last commit:

# Discard changes in working directory
git restore app.js

# Discard all changes
git restore .

# Old syntax (still works)
git checkout -- app.js

Undo Staged Changes

Remove from staging area:

# Unstage file
git restore --staged app.js

# Unstage all files
git restore --staged .

# Old syntax
git reset HEAD app.js
git reset HEAD

Undo Last Commit

Three options depending on needs:

# Keep changes, remove commit
git reset --soft HEAD~1

# Keep changes in working directory
git reset --mixed HEAD~1 # default

# Discard changes completely
git reset --hard HEAD~1

# Safe option for pushed commits
git revert HEAD

Reset vs Revert 🔄

Reset (Rewrites History) ⚠️

Use only on unpushed commits!

# Soft reset: keep changes staged
git reset --soft HEAD~1
# Changes ready to recommit

# Mixed reset: keep changes unstaged (default)
git reset --mixed HEAD~1
# Changes in working directory

# Hard reset: discard changes
git reset --hard HEAD~1
# Dangerous! Changes lost

Revert (Safe for Shared Branches) ✅

Creates new commit that undoes changes:

# Create commit that undoes previous
git revert HEAD

# Revert specific commit
git revert a1b2c3d

# Revert without committing
git revert --no-commit a1b2c3d

# Revert multiple commits
git revert a1b2c3d..x1y2z3d

Visual Comparison

Original timeline:
commit A → commit B → commit C → commit D

git reset --soft HEAD~1:
commit A → commit B → commit C
(D's changes staged)

git revert HEAD:
commit A → commit B → commit C → commit D → commit E (undoes D)

Amending Commits ✏️

Amend Last Commit

Fix message or add forgotten files:

# Fix commit message
git commit --amend -m "Corrected message"

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

# Edit both message and content
git add file.js
git commit --amend

# Don't create new commit hash (only works if not pushed)
# Rewrites history

Amending Already Pushed Commits

# Fix locally
git commit --amend -m "Fixed message"

# Force push to remote (risky!)
git push origin main --force-with-lease

# --force-with-lease is safer than --force
# Fails if someone else pushed changes

Interactive Rebase 🎯

Powerful tool to rewrite commit history. Use only before pushing!

Basic Interactive Rebase

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

# Opens editor with commits:
pick a1b2c3d Add feature
pick x1y2z3d Fix typo
pick m1n2o3p Add tests

# Modify, save, and exit
# Git replays commits with your changes

Rebase Commands

pick (p)   - Use commit
reword (r) - Use commit, edit message
edit (e) - Use commit, but stop to amend
squash (s) - Use commit, but meld into previous
fixup (f) - Like squash, but discard log message
drop (d) - Remove commit
exec (x) - Run shell command

Example: Squashing Commits

# You have messy commit history:
pick a1b2c3d Add user model
pick x1y2z3d Fix user model
pick m1n2o3p Add user tests

# Change to:
pick a1b2c3d Add user model
squash x1y2z3d Fix user model
squash m1n2o3p Add user tests

# Result: 1 commit combining all 3
# With combined message

Example: Reordering Commits

# Current:
pick a1b2c3d Feature A
pick x1y2z3d Feature B

# Want:
pick x1y2z3d Feature B
pick a1b2c3d Feature A

# Just reorder lines in editor
# Git replays in new order

Example: Editing Commit Messages

# Current:
pick a1b2c3d Add feature

# Change to:
reword a1b2c3d Add user authentication feature

# Git stops at this commit
# Opens editor for new message
# Continues with remaining commits

Aborting Rebase

# Something went wrong?
git rebase --abort

# Stops and returns to original state
# No history changed

Cleaning Up History

Combining Multiple Commits

# You made 5 commits for one feature
git log --oneline
a1b2c3d WIP
x1y2z3d Fix
m1n2o3p More fixes
p1q2r3s Update tests
z9y8x7w Final touches

# Combine into one:
git rebase -i HEAD~5

# Edit:
pick a1b2c3d WIP
squash x1y2z3d Fix
squash m1n2o3p More fixes
squash p1q2r3s Update tests
squash z9y8x7w Final touches

# Result: single clean commit

Removing Bad Commits

# Oops! Committed sensitive data
git log --oneline
# a1b2c3d Oops! Added password
# x1y2z3d Feature X

# Remove it:
git rebase -i HEAD~2

# Edit:
drop a1b2c3d Oops! Added password
pick x1y2z3d Feature X

# Commit is completely removed

Cherry-Picking 🍒

Copy specific commits to another branch:

# Apply specific commit to current branch
git cherry-pick a1b2c3d

# Apply multiple commits
git cherry-pick a1b2c3d x1y2z3d m1n2o3p

# Apply range of commits
git cherry-pick a1b2c3d..m1n2o3p # Excludes a1b2c3d
git cherry-pick a1b2c3d^..m1n2o3p # Includes a1b2c3d

Real-World Example

# Bug fix was committed to develop
git log develop
# a1b2c3d Fix critical bug

# Need it in main now!
git checkout main
git cherry-pick a1b2c3d

# Commit applied to main
# Still exists in develop
# Creates new commit (different hash)

Cherry-Pick with Conflicts

# If there are conflicts:
# 1. Resolve them
git add fixed-file.js

# 2. Continue
git cherry-pick --continue

# Or abort
git cherry-pick --abort

Reflog: Recovery Tool 🆘

Reflog tracks where HEAD has been. Perfect for recovery!

Viewing Reflog

# See recent HEAD positions
git reflog

# Output:
# a1b2c3d HEAD@{0}: commit: Last commit
# x1y2z3d HEAD@{1}: rebase: Some commit
# m1n2o3p HEAD@{2}: checkout: switching to main
# p1q2r3s HEAD@{3}: reset: hard reset to previous

Recovering Lost Commits

# You did hard reset and lost commits
git reset --hard HEAD~5

# See what you lost
git reflog

# a1b2c3d HEAD@{0}: reset: hard reset
# (this is old position, has your commits)

# Get back to lost commits
git reset --hard a1b2c3d

# Or create branch at lost position
git checkout -b recovery a1b2c3d

Recovering Deleted Branch

# You deleted a branch
git branch -D feature

# Where is it?
git reflog

# a1b2c3d HEAD@{5}: branch: Created
# (this has your commits)

# Recreate it
git checkout -b feature-restored a1b2c3d

Search History 🔍

Find Commits by Message

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

# Case-insensitive search
git log -i --grep="LOGIN"

# Search with regex
git log --grep="fix.*typo"

Find Commits by Content

# Find commits that added/removed text
git log -S "password"

# Find commits that changed specific function
git log -S "function_name"

# Find commits that touched specific word
git log -G "searchTerm" # Regex version

Find by Author

# Commits by specific person
git log --author="John Doe"

# Case-insensitive
git log -i --author="john"

# Commits by anyone except
git log --author="^(?!John)"

Find by Date

# Commits since date
git log --since="2024-01-01"

# Commits until date
git log --until="2024-01-31"

# Human-readable dates work
git log --since="2 weeks ago"
git log --since="1 month ago"
git log --before="yesterday"
# Show commits touching file, by author, since date
git log --since="1 month ago" \
--author="John" \
--grep="feature" \
-- path/to/file.js

# Commits where code was changed by specific author
git log -S "variable_name" --author="John"

# Recent changes on specific file
git log -p --follow -- src/app.js

Viewing History

One-Line History

# Compact view
git log --oneline

# a1b2c3d Add user auth
# x1y2z3d Fix login bug
# m1n2o3p Add tests

# With dates
git log --oneline --date=short --format="%h %ad %s"

Branching History

# Show as graph
git log --graph --oneline --all

# Better visualization:
git log --graph --oneline --all --decorate

# Really pretty:
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

File History

# See all changes to file
git log -p -- app.js

# See when lines were changed
git blame app.js

# Output shows:
# a1b2c3d (John Doe 2024-01-15 10:30:45 -0500) function hello() {
# x1y2z3d (Jane Smith 2024-01-14 14:20:00 -0500) return 'hi';

Diff History

# Show what changed in each commit
git log -p

# Show statistics
git log --stat

# Show patch with context
git log -p -5 # Last 5 commits with diffs

Best Practices ⚠️

The Golden Rules

DO:
- Use reset/rebase on LOCAL branches only
- Use revert for shared/public branches
- Commit frequently with clear messages
- Review history before pushing
- Use reflog for recovery

DON'T:
- Force push to shared branches (without discussion)
- Rewrite history on main/develop
- Cherry-pick across unrelated features
- Forget to test after rebasing
- Ignore merge conflicts

When to Use Each Tool

SituationUseCommand
Fix message on last commitAmendgit commit --amend
Combine local commitsSquash via rebasegit rebase -i
Undo on local branchResetgit reset --soft HEAD~1
Undo on shared branchRevertgit revert HEAD
Copy specific commitCherry-pickgit cherry-pick <hash>
Recover lost commitsRefloggit reflog
Clean up before pushInteractive rebasegit rebase -i

Real-World Scenarios 📋

Scenario: Messy Local Commits Before Push

# You have 5 commits for one feature
git log --oneline
# a1b2c3d WIP
# x1y2z3d Fix
# m1n2o3p More fixes
# p1q2r3s Update tests
# z9y8x7w Final

# Clean up before pushing
git rebase -i HEAD~5

# Squash all into one:
# pick a1b2c3d WIP
# squash x1y2z3d Fix
# squash m1n2o3p More fixes
# squash p1q2r3s Update tests
# squash z9y8x7w Final

# Push clean history
git push origin feature-clean

Scenario: Accidental Commit to Wrong Branch

# You committed to main instead of feature
# main has: a1b2c3d, x1y2z3d (wrong), m1n2o3p

# Create feature branch at wrong commit
git branch feature-recovery x1y2z3d

# Reset main to before the wrong commit
git reset --hard a1b2c3d

# Now work on feature branch
git checkout feature-recovery

Scenario: Recovering Lost Work

# You did hard reset and lost everything
git reset --hard HEAD~10

# Check reflog
git reflog

# Find commit before reset
# a1b2c3d HEAD@{2}: (this is your lost work)

# Recovery options:
# 1. Create branch
git branch lost-work a1b2c3d

# 2. Create and switch to it
git checkout -b lost-work a1b2c3d

# 3. Reset to it
git reset --hard a1b2c3d

You've mastered Git! You now understand:

  • Version control fundamentals
  • Branching and workflows
  • Advanced commands
  • History management and recovery

Time to practice and build your Git expertise! 🚀


Congratulations! You've completed the Git Mastery guide. Keep practicing and refer back to these sections as needed. Happy coding! 🚀✨