Git Advanced: The Commands I Wish I Knew Earlier (2026)
Most developers know add, commit, push. But Git has so much more power. These are the commands that changed how I work.
Rewriting History (Use with Care!)
# Modify your LAST commit (most useful command ever!)
# Forgot a file? Typo in commit message? This fixes it:
git add forgotten-file.js
git commit --amend -m "Fixed commit message"
# Reorder, squash, or split recent commits:
git rebase -i HEAD~3 # Interactive rebase of last 3 commits
# Opens editor with options:
# pick = use commit as-is
# reword = change message only
# edit = pause to modify files
# squash = merge into previous commit
# fixup = merge into previous (discard message)
# drop = remove entirely
# Example: Squash last 3 "WIP" commits into one clean commit:
# Change first to "pick", rest to "squash"
# Save → Git opens editor for combined message
# Update a commit message from earlier (not just the last):
git rebase -i HEAD~5
# Find the commit → change "pick" to "reword"
# Save → edit each message
# Split one commit into two:
git rebase -i HEAD~3
# Find target commit → change "pick" to "edit"
# Git pauses at that commit:
git reset HEAD~1 # Unstage but keep files
git add file1.js
git commit -m "Part 1: file1 changes"
git add file2.js
git commit -m "Part 2: file2 changes"
git rebase --continue # Continue rebasing
Stashing: Save Work Without Committing
# The basic stash (saves all modified/tracked files):
git stash
# Your working directory is now clean! Go work on something else.
# List all stashes:
git stash list
# Output: stash@{0}: WIP on feature-login: abc1234
# stash@{1}: WIP on main: def5678
# Restore most recent stash:
git stash pop # Apply and remove from stash list
git stash apply # Apply but keep in stash list (safer)
# Restore specific stash:
git stash apply stash@{1}
# Stash with a name (essential when you have multiple stashes):
git stash push -m "WIP: OAuth implementation half-done"
# Stash untracked files too (new files not yet added):
git stash push -u -m "Including new files"
# Stash specific files only:
git stash push -m "Only config changes" src/config.js .env.example
# Show what's in a stash before applying:
git stash show -p stash@{0} # Full diff of the stash
# Drop or clear stashes:
git stash drop stash@{0} # Remove one
git stash clear # Remove ALL stashes
Searching Through History
# Search COMMIT MESSAGES across all branches:
git log --all --grep="bug fix" # Find commits mentioning "bug fix"
git log --all --grep="auth" --oneline # Compact view
# Search CODE CONTENT through history:
git log -S "functionName" --oneline # When was this text added/removed?
git log -G "pattern" --oneline # Regex search through diffs
git log -p -S "TODO" # Show actual diff where text appears
# Search current codebase:
git grep "error" # Search all tracked files for "error"
git grep -n "export" src/ # With line numbers, in specific dir
git grep --count "import" ./src/ # Count matches per file
# Who wrote this line? (blame!)
git blame src/utils.js # Line-by-line author history
git blame -L 10,20 src/utils.js # Lines 10-20 only
git blame -e src/utils.js # Include email addresses
# Find which commit broke something:
git bisect start
git bisect bad # Current version is broken
git bisect good v2.0.0 # This version worked
# Git automatically checks out middle commits
# After each checkout: test, then:
git bisest good # This version works
git bisect bad # This version is broken
# Repeat until Git finds the exact breaking commit!
git bisect reset # Done — return to original branch
Branch Management Like a Pro
# See all branches with last commit info:
git branch -vv
# Output: * feature-auth abc1234 [origin/feature-auth] Add OAuth login
# main def5678 [origin/main] Release v2.0
# Rename branch (local + remote):
git branch -m old-name new-name
git push origin :old-name new-name # Delete remote old, push new
# Others need: git fetch --prune && git branch -u origin/new-name new-name
# Compare branches:
git log main..feature-branch --oneline # Commits in feature but not in main
git log feature-branch..main --oneline # Commits in main but not in feature
git diff main...feature-branch # Diff from merge base (not common ancestor)
# Merge vs Rebase (quick reference):
git merge feature-branch # Creates merge commit, preserves history
git rebase main # Linear history, replays commits on top of main
# Safe force-push (only if nobody else pushed to this branch):
git push --force-with-lease origin feature-branch
# Safer than regular --force because it checks if remote changed
# Recover a deleted branch:
git reflog # Find the SHA of the branch tip
git branch recovered-branch abc1234 # Recreate branch at that SHA
Working with Remote Repositories
# See all remotes:
git remote -v
# Add a remote:
git remote upstream https://github.com/original/repo.git
# Fetch from a specific remote without merging:
git fetch upstream
git log HEAD..upstream/main --oneline # What's new upstream?
# Track a new remote branch:
git checkout --track origin/new-feature
# Same as: git checkout -b new-feature origin/new-feature
# Clean up stale remote-tracking branches:
git fetch --prune
# Or: git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -d
# Push to multiple remotes simultaneously:
git remote set-url --add --push all git@github:user/repo.git
git remote set-url --add --push all git@gitlab:user/repo.git
git push all main # Pushes to both GitHub and GitLab!
# Cherry-pick specific commits:
git cherry-pick abc1234 # Apply one commit from another branch
git cherry-pick abc1234 def5678 # Apply multiple commits
git cherry-pick --no-commit abc1234 # Apply changes without committing
git cherry-pick --edit abc1234 # Edit commit message before applying
Troubleshooting Common Problems
# ❌ Committed to wrong branch:
git reset --soft HEAD~1 # Undo commit, keep changes staged
git checkout correct-branch
git commit # Re-commit on correct branch
# ❌ Accidentally committed sensitive data (passwords, keys):
# Option A: If NOT yet pushed:
git rm secrets.json
git commit -m "Remove secrets"
# Use git-filter-repo or BFG Repo Cleaner if already pushed!
# ❌ Merge conflict hell:
# Don't panic. Step by step:
git status # See conflicted files
# Open each file, look for: <<<<<<< HEAD, =======, >>>>>>> feature
# Edit to keep what you want, remove markers
git add resolved-file.js # Mark as resolved
git commit # Complete the merge
# Pro tip: use VS Code's merge tool or git mergetool
# ❌ Need to undo something?
git restore file.txt # Discard working directory changes (uncommitted)
git restore --staged file.txt # Unstage (keep changes)
git reset --hard HEAD~1 # DANGEROUS: Remove last commit AND changes!
git reflog # Recovery mode: find lost commits here
# ❌ Large file slowing down repo:
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sort -rnk3 | head -20
# Find large objects, then use BFG Repo Cleaner or git filter-repo
Which Git command here is new to you? What's your favorite Git trick that wasn't included?
Follow @armorbreak for more practical developer guides.
Top comments (0)