Git Commands Cheat Sheet — Every Command You Actually Use
Git has hundreds of commands but most developers use fewer than 20 daily. This cheat sheet covers the most important Git commands with practical examples, tips for complex scenarios, tricks for undoing mistakes without losing work, and workflows for branches, stashing, rebasing, and finding bugs in history. Whether you're a daily Git user or learning the advanced commands, this guide covers everything from status and commits to bisect, cherry-pick, and worktrees.
30+
essential commands covered with examples
git reflog
the "undo everything" safety net — never lose work
git stash
save work without committing for context switching
git bisect
binary search through history to find breaking commit
Essential Daily Commands
# ─── Status and Inspection ───────────────────────────────────────────────────
git status # What's changed? (modified, staged, untracked)
git status -s # Short format: M=modified, A=added, ?=untracked
git diff # See unstaged changes (what's not yet staged)
git diff --staged # See staged changes (what will be in next commit)
git diff main..feature # Diff between two branches
git log --oneline -20 # Recent commits (compact, one line each)
git log --oneline --graph --all # ASCII branch visualization
git log --follow -p file.txt # Full history + diffs for a specific file
# ─── Staging and Committing ──────────────────────────────────────────────────
git add file.txt # Stage specific file
git add src/ # Stage all files in a directory
git add -p # Interactively stage hunks (RECOMMENDED — review each change)
git commit -m "feat: add login"
git commit --amend # Edit last commit message (unpushed only!)
git commit --amend --no-edit # Add staged changes to last commit without editing message
# ─── Branches ────────────────────────────────────────────────────────────────
git branch # List local branches
git branch -a # List all branches (including remote tracking)
git branch -v # Branches with last commit message
git checkout -b feature/login # Create and switch to new branch
git switch main # Switch branch (modern syntax, Git 2.23+)
git switch -c feature/login # Create and switch (modern syntax)
git branch -d feature/done # Delete merged branch
git branch -D feature/wip # Force delete (even if unmerged)
git merge feature/login # Merge branch into current
git merge --no-ff feature/x # Merge with a merge commit (even if fast-forward possible)
# ─── Remote ──────────────────────────────────────────────────────────────────
git fetch origin # Download changes (don't merge — safe preview)
git fetch --all # Fetch all remotes
git pull origin main # Fetch + merge (shortcut)
git pull --rebase # Fetch + rebase instead of merge (linear history)
git push origin feature/login # Push branch to remote
git push -u origin feature/login # Push and set upstream (then just git push)Undoing Mistakes — Safe and Destructive Options
Know which undo operations are destructive
# ─── Unstage (safe — keeps changes) ─────────────────────────────────────────
git restore --staged file.txt # Unstage file, keep working tree changes
git reset HEAD file.txt # Same (older syntax)
# ─── Discard working tree changes (DESTRUCTIVE — loses changes) ──────────────
git restore file.txt # Discard changes to one file
git restore . # Discard ALL unstaged changes in repo
# ─── Undo commits ────────────────────────────────────────────────────────────
git reset --soft HEAD~1 # Undo last commit, keep changes STAGED
git reset HEAD~1 # Undo last commit, keep changes UNSTAGED
git reset --hard HEAD~1 # Undo last commit, DISCARD changes (destructive!)
git reset --hard HEAD~3 # Undo last 3 commits and discard all changes
# ─── Safe revert (creates new commit) ───────────────────────────────────────
git revert abc1234 # Create new commit undoing specific commit
# Use revert on shared/pushed branches — never reset shared history!
# ─── The Ultimate Safety Net ─────────────────────────────────────────────────
git reflog # See every position HEAD has been in (last 90 days)
git reflog --all # Include all refs (branches, stashes)
git reset --hard HEAD@{2} # Go back to 2 reflog entries ago (undo an undo!)
git checkout HEAD@{5} -- file.txt # Recover a specific file from 5 moves agoStashing — Save Work Without Committing
git stash # Save all uncommitted changes (tracked files)
git stash -u # Include untracked files too
git stash push -m "WIP: login form" # Save with a descriptive label
git stash list # See all stashes with indices
# stash@{0}: On feature/login: WIP: login form
# stash@{1}: WIP on main: quick experiment
git stash pop # Apply most recent stash AND delete it
git stash apply stash@{1} # Apply specific stash (keeps stash in list)
git stash drop stash@{1} # Delete a specific stash
git stash clear # Delete ALL stashes (irreversible!)
# Advanced stash operations
git stash push -m "only styles" src/styles.css # Stash only specific file
git stash show -p stash@{0} # Show diff of what's in a stash
git stash branch feature/from-stash stash@{0} # Create branch from stash
# Partial stash (interactive — like git add -p)
git stash push -p # Choose which hunks to stashAdvanced Tips and Power User Tricks
# ─── Finding Bugs with Bisect ────────────────────────────────────────────────
git bisect start
git bisect bad # Current commit is broken
git bisect good v1.0.0 # This tag was working
# Git checks out the middle commit — test it manually, then:
git bisect good # or: git bisect bad
# Repeat until Git finds the exact breaking commit (takes log2(N) steps)
git bisect reset # Return to HEAD when done
# Automated bisect with a test script:
git bisect run npm test # Runs test, uses exit code (0=good, 1=bad)
# ─── Cherry-Pick ─────────────────────────────────────────────────────────────
git cherry-pick abc1234 # Apply a specific commit to current branch
git cherry-pick abc1234..def5678 # Apply a range of commits
git cherry-pick -n abc1234 # Stage changes without committing (--no-commit)
# ─── Interactive Rebase ──────────────────────────────────────────────────────
git rebase -i HEAD~5 # Rewrite last 5 commits interactively
# Commands in editor:
# pick = keep commit as-is
# reword = edit commit message
# squash = merge into previous commit (keep message)
# fixup = merge into previous commit (discard message)
# drop = delete commit entirely
# exec = run shell command between commits
# ─── Searching History ───────────────────────────────────────────────────────
git log --grep="login" # Commits whose message mentions "login"
git log -S "functionName" # Commits that added/removed "functionName" in code
git log -G "regex.*pattern" # Commits where code matches regex
git log --author="Alice" # Commits by specific author
git log --since="2 weeks ago" # Commits within timeframe
git show abc1234 # Show full diff of a specific commit
git show abc1234 --stat # Show only file summary of a commit
git blame file.txt # Who last changed each line and when
git blame -L 10,25 file.txt # Blame for lines 10-25 only
# ─── Useful Aliases ──────────────────────────────────────────────────────────
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.st "status -sb"
git config --global alias.undo "reset HEAD~1"
git config --global alias.save "stash push -m"
git config --global alias.aliases "config --get-regexp alias"Branch and Merge Strategies
| Item | Strategy | When to Use |
|---|---|---|
| git merge (default) | Creates a merge commit preserving full branch history | Feature branches merged to main, team collaboration where history is important |
| git merge --ff-only | Only merges if fast-forward possible (linear history) | Small updates where merge commits would add noise |
| git rebase onto main | Replays your commits on top of target branch | Keeping feature branches up-to-date with main before PR |
| git merge --squash | Combines all branch commits into one staged change | Squashing messy WIP commits before merging |
| git rebase -i (interactive) | Rewrite history: squash, reorder, edit, delete commits | Cleaning up local commits before sharing a PR |
Golden rule: never rewrite shared history
Git Config and Global Setup
# Set identity (required)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Set default editor (for commit messages, rebase)
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim" # Vim
# Set default branch name for new repos
git config --global init.defaultBranch main
# Faster rebasing and better diff output
git config --global pull.rebase true # pull --rebase by default
git config --global rebase.autoSquash true # auto-apply fixup commits
git config --global diff.colorMoved zebra # color moved code blocks differently
# Store credentials (macOS keychain)
git config --global credential.helper osxkeychain
# View all config
git config --list --show-originResolving Merge Conflicts
Start the merge or rebase
git merge feature-branch or git pull. Git stops and reports conflicts: "CONFLICT (content): Merge conflict in src/app.ts"
Open conflicting files
Conflict markers: <<<<<<< HEAD is your version, ======= separates versions, >>>>>>> feature-branch is theirs. Edit to keep the right code — delete all markers.
Stage resolved files
git add src/app.ts for each resolved file. Never git add -A blindly — only add files you've actually resolved.
Continue or commit
For merge: git commit (message auto-generated). For rebase: git rebase --continue. To abort entirely: git merge --abort or git rebase --abort.
Use a merge tool (optional)
git mergetool opens a 3-way diff editor. VS Code: set git config --global merge.tool vscode and git config --global mergetool.vscode.cmd "code --wait $MERGED"