Diff, Stash & Tags 🔧
Three essential Git tools for advanced workflows: understanding changes, temporarily saving work, and marking releases.
Diff: Understanding Changes 📊
Diff shows the differences between versions of files.
Basic Diff
See unstaged changes in your working directory:
git diff
# Output example:
# diff --git a/app.js b/app.js
# index a1b2c3d..x1y2z3d 100644
# --- a/app.js
# +++ b/app.js
# @@ -5,3 +5,4 @@
# console.log('Start');
# -console.log('Old line');
# +console.log('New line');
# console.log('End');
Understanding Diff Output
diff --git a/app.js b/app.js # File being compared
index a1b2c3d..x1y2z3d 100644 # Hash and permissions
--- a/app.js # Original version (before)
+++ b/app.js # New version (after)
@@ -5,3 +5,4 @@ # Starting at line 5, 3 lines
# (new version: 5, 4 lines)
console.log('Start'); # Context (unchanged)
-console.log('Old line'); # Removed (-)
+console.log('New line'); # Added (+)
console.log('End'); # Context
Diff Variations
# Show staged changes (ready to commit)
git diff --staged
# or
git diff --cached
# Show diff between branches
git diff main..feature
git diff main feature
# Show what feature has that main doesn't
git diff main...feature
# Show diff for specific file
git diff app.js
# Show diff between commits
git diff a1b2c3d x1y2z3d
# Show diff with statistics
git diff --stat
# Show just file names that changed
git diff --name-only
# Show changes with different formatting
git diff --color-words # Word-level diff
git diff --unified=5 # 5 lines of context
Word-Level Diff
# Color words that changed
git diff --color-words
# Example output:
# The quick brown fox → The fast brown fox
# Only "quick" → "fast" highlighted
Viewing Formatted Diff
# Unified diff (default)
git diff --unified=3
# Context diff
git diff --ignore-all-space
git diff --ignore-space-at-eol
# See changes in patch format
git diff --patch
Diff Between States
Working Directory vs Staging
# What you've changed but not staged
git diff
Staging vs Repository
# What you've staged but not committed
git diff --staged
Repository Versions
# Between commits
git diff a1b2c3d x1y2z3d
# Between branches
git diff main feature
# Between HEAD and previous commit
git diff HEAD~1
Summary Diff
# Just show statistics
git diff --stat
# Output:
# app.js | 5 +++++--
# config.js | 3 +++
# 2 files changed, 8 insertions(+), 2 deletions(-)
# Show which files changed
git diff --name-only
# Show files and change type
git diff --name-status
# Output:
# M app.js (modified)
# A config.js (added)
# D old-file.js (deleted)
Viewing History Diffs
Diff for Specific Commit
# See changes in a commit
git show a1b2c3d
# See specific file in a commit
git show a1b2c3d:app.js
# See diff from previous commit
git show a1b2c3d
# See diff between commits
git diff a1b2c3d x1y2z3d
Log with Diff
# Show commits with diffs
git log -p
# Show last 3 commits with diffs
git log -p -3
# Show diff for specific file's history
git log -p app.js
# Show statistics
git log --stat
Stash: Saving Work Temporarily 📦
Stash saves your work without committing it. Perfect for interruptions!
Basic Stash
# Save current changes
git stash
# Clears working directory
# Changes stored safely
# Your work is ready to be brought back
Real-World Scenario
# You're working on feature
git add .
git commit -m "WIP: Adding new feature"
# Suddenly, critical bug reported!
# Save your work
git stash
# Working directory is clean
# You can now switch branches safely
git checkout main
# Fix bug...
# When done
git checkout feature
git stash pop # Get your work back
Stash List
# See all stashes
git stash list
# Output:
# stash@{0}: WIP on feature: a1b2c3d Add new UI
# stash@{1}: On main: x1y2z3d Fix typo
# stash@{2}: WIP on develop: m1n2o3p Refactor
# Most recent first
Retrieving Stash
# Apply and remove (most common)
git stash pop
# Apply but keep stash
git stash apply
# Apply specific stash
git stash apply stash@{1}
git stash pop stash@{1}
# Apply stash to new branch (prevents conflicts)
git stash branch feature-from-stash
Stashing Selectively
# Stash only staged changes
git stash push --staged
# Stash only unstaged changes
git stash push --keep-index
# Stash with descriptive message
git stash save "WIP: Feature login system"
# or modern way:
git stash push -m "Feature login system"
# Stash specific files only
git stash push app.js config.js
# Include untracked files
git stash --include-untracked
git stash -u
Viewing Stash Contents
# See what's in a stash
git stash show
# See detailed diff
git stash show -p
# Show specific stash
git stash show stash@{1} -p
Cleaning Up Stashes
# Delete specific stash
git stash drop stash@{1}
# Delete all stashes
git stash clear
# Be careful! This is permanent
Stashing Best Practices
# Good practice: named stashes
git stash push -m "Feature authentication WIP"
# Don't leave stashes indefinitely
git stash list # Check often
# Pop stashes soon after creating
# Stashes from weeks ago might be hard to reapply
Tags: Marking Releases 🏷️
Tags mark important points in history, usually releases.
Lightweight Tags
Simple reference to a commit:
# Create lightweight tag
git tag v1.0.0
# Just points to current commit
# Minimal storage
Annotated Tags
Full object with metadata:
# Create annotated tag
git tag -a v1.0.0 -m "Release version 1.0.0"
# Includes:
# - Tagger name & email
# - Date
# - Message
# - Can be signed
Creating Tags
# Tag current commit
git tag v1.0.0
# Tag with message
git tag -a v1.0.0 -m "Release 1.0.0"
# Tag previous commit
git tag v1.0.0 a1b2c3d
# Tag with annotation
git tag -a v1.0.0 a1b2c3d -m "Release 1.0.0"
# Sign tag (requires GPG)
git tag -s v1.0.0 -m "Signed release"
Viewing Tags
# List all tags
git tag
# Search tags
git tag -l "v1.*" # Find all v1.x tags
# Show tag details
git show v1.0.0
# Show just message
git tag -n # Show with first line of message
git tag -n3 # Show first 3 lines
Pushing Tags
# Push specific tag
git push origin v1.0.0
# Push all tags
git push origin --tags
# Force push tag (rarely needed)
git push origin v1.0.0 --force
# Delete tag locally
git tag -d v1.0.0
# Delete tag on remote
git push origin --delete v1.0.0
git push origin :v1.0.0 # Older syntax
Semantic Versioning 📌
Standard versioning format: MAJOR.MINOR.PATCH
# MAJOR: Breaking changes
git tag v2.0.0 # Completely new API
# MINOR: New features, backwards compatible
git tag v1.1.0 # Added new functions
# PATCH: Bug fixes
git tag v1.0.1 # Fixed bugs
# Pre-release
git tag v1.0.0-alpha
git tag v1.0.0-beta
git tag v1.0.0-rc.1
Release Workflow with Tags
# 1. Ensure main is clean
git checkout main
git pull origin main
# 2. Create release commit (update version file)
echo "1.0.0" > VERSION
git add VERSION
git commit -m "Bump version to 1.0.0"
# 3. Create tag
git tag -a v1.0.0 -m "Release version 1.0.0"
# 4. Push everything
git push origin main
git push origin v1.0.0
# 5. Create release on GitHub
# (with changelog, artifacts, etc.)
Comparing Tags
# See changes between tags
git diff v1.0.0 v1.1.0
# See commits between tags
git log v1.0.0..v1.1.0
# See commits since tag
git log v1.0.0..HEAD
# Show tag info
git log --oneline v1.0.0..HEAD
Common Patterns 🎯
Finding Changes
# What changed in last commit?
git show HEAD
# What changed in feature branch?
git diff main..feature
# What files changed?
git diff --name-only main..feature
# See specific file changes
git diff main..feature -- app.js
Stashing for Quick Switch
# Working on feature, need to check main
git stash # Save work
git checkout main # Switch
# Do work...
git checkout feature # Go back
git stash pop # Restore work
Creating Releases
# After all work is done
git tag -a v2.0.0 -m "Major release: New API"
git push origin v2.0.0
# Now create GitHub Release with:
# - Changelog
# - Download links
# - Migration guide
Advanced Diff Options
# Ignore whitespace changes
git diff -w
git diff --ignore-all-space
# Show empty diff context
git diff --function-context
# Patience algorithm (better for some files)
git diff --patience
# Histogram algorithm (faster)
git diff --histogram
# Compare ignoring specific files
git diff ':!package-lock.json'
# See what commits are ahead/behind
git log origin/main..main # Ahead
git log main..origin/main # Behind
You've learned three powerful tools! Next, master Managing History to control your Git timeline. ⏱️
Next: Managing History